函数
;;;;函数
(defun name (parameter*)
"Optional documentation string"
body-form*)
;;;形参列表
;;必要形参,个数必须一致
;;可选形参&optional
(defun foo (a b &optional c d)
(list a b c d))
;;a b 必须输入 c d 可以不输入,默认nil
;;默认值,并且可以用前面参数的值进行运算,是否提供默认值判断-supplied-p(t nil)
(defun foo (a &optional (b 10))
(list a b))
(defun make-rectangle (width &optional (height width))
...)
(defun foo (a &optional (b 10) (c 30 c-supplied-p))
(list a b c c-supplied-p))
;;剩余形参&rest,可变数量的参数收集到一个列表里传给函数
(defun format (stream string &rest values)
...)
(defun + (&reset numbers)
...)
;;关键字形参&key
(defun foo (&key (a 0) (b 10 b-supplied-p) (c (+ a b)))
(list a b c b-supplied-p))
(defun foo (&key ((:apple a) 0) ((:box b) 10 b-supplied-p) ((:charlie c) (+ a b)))
(list a b c b-supplied-p))
(foo :apple 10)
;;混合不同类型
;;函数返回值
;;默认最后一个表达式的值作为返回值,从中间返回可以用RETURN-FROM 函数名
(defun foo (n)
(dotimes (i 10)
(dotimes (j 10)
(when (> (* i j) n)
(return-form foo (list i j))))))
;;高阶函数,作为数据的函数
;;获取函数对象(function foo) #'foo
;;FUNCALL APPLY调用函数
(foo 1 2 3) ====(funcall #'foo 1 2 3)
;;建设性的用法
(defun plot (fn min max step)
(loop for i from min to max by step do
(loop repeat (funcall fn i) do (format t "*"))
(format t "~%")))
;;如果传给plot的参数在一个列表里(plot-data)
; funcall调用的时候只能分开列表
(plot (first plot-data) (second plot-data) (third plot-data) (fourth plot-data))
; 这样太麻烦了,可以直接这样调用
(APPLY #'plot plot-data)
;加入plot-data只含有(最小值 最大值 步长),还可以这样调用
(APPLY #'plot #'exp plot-data)
;;;匿名函数(lambda (parameters) (body))
;;;已知道只是用一次
(plot #'(lambda (x) (* 2 x)) 0 10 1)
;;;另外一个用途是制作闭包
;int i = 1
;fuction #'foo = foo
(eq #'double (car (list #'double)))
直接1和"aff"就定义一个整数和字符串对象
同理(lambda (x) (* x 2)) 定义了一个函数对象
可以同时定义相同名字的函数和变量
(setq double 2)
(defun double (x) (* 2 x))
(double double)名字出现出现在列表首位,或者有前缀#'被认为是函数,其他是变量。
(symbol-value 'double)获取一个变量
(symbol-function 'double)获取一个函数
函数也是普通对象可以赋值
(setf x 'append)
(eq (symbol-value x) (symbol-funciton 'append)) t
(defun double (x) (* 2 x)等价于
(setf (symbol-function 'double)
#'(lambda (x) (* 2 x)))