LISP - 函数
Lisp - 函数
Section titled “Lisp - 函数”函数是任何 Lisp 程序的基本构建块。它们是执行特定任务的独立代码单元。在 Lisp 中,函数是头等公民,这意味着它们可以像数字或字符串等其他数据类型一样,存储在变量中,作为参数传递给其他函数,并作为值返回。
使用 defun 定义函数
Section titled “使用 defun 定义函数”defun 宏用于定义具名函数。其基本语法如下:
(defun function-name (parameter-list) "Optional documentation string." function-body)function-name:一个用于命名函数的符号。parameter-list:一个用于函数参数的符号列表。documentation string:描述函数功能的可选字符串。这是一个最佳实践,可以通过(documentation 'function-name 'function)获取。function-body:一个或多个 Lisp 表达式。最后求值的表达式的值将作为函数的返回值隐式返回。
示例:计算圆的面积
Section titled “示例:计算圆的面积”让我们定义一个计算圆面积的函数。注意内置常量 pi 的使用。
(defun circle-area (radius) "Calculates the area of a circle given its radius." (* pi radius radius))
;; 调用函数并打印结果(format t "Area of a circle with radius 10: ~f~%" (circle-area 10))Area of a circle with radius 10: 314.15927高级参数列表
Section titled “高级参数列表”Lisp 函数使用 lambda 列表关键字支持高度灵活的参数列表。
&optional:用于可带默认值的可选参数。&rest:用于可接受任意数量额外参数的可变参数函数。&key:用于通过名称而不是位置指定的参数。
示例:灵活的问候函数
Section titled “示例:灵活的问候函数”(defun greet (name &key (greeting "Hello") (punctuation "!")) "Greets a person with customizable options." (format nil "~a, ~a~a" greeting name punctuation))
;; --- 用法 ---
;; 默认参数(print (greet "Alice"))
;; 覆盖一个关键字参数(print (greet "Bob" :greeting "Hi"))
;; 覆盖所有关键字参数(顺序无关)(print (greet "Charlie" :punctuation "." :greeting "Good morning"))"Hello, Alice!""Hi, Bob!""Good morning, Charlie."如前所述,函数会隐式返回其最后求值表达式的值。要从块内部(例如循环)提前返回,可以使用 return-from。
示例:使用 return-from 进行显式返回
Section titled “示例:使用 return-from 进行显式返回”(defun find-first-odd (numbers) "Returns the first odd number in a list, or NIL if none are found." (dolist (num numbers) ; dolist 隐式创建一个名为 nil 的块 (when (oddp num) (return-from find-first-odd num))) ;; 只有当循环完成且没有找到奇数时,才会到达此部分。 nil)
(print (find-first-odd '(2 4 5 6 7)))(print (find-first-odd '(2 4 6 8)))5NILdefun 宏会自动将函数体包装在一个与函数同名的块中。(return-from find-first-odd num) 会立即退出 find-first-odd 函数并返回 num 的值。
高阶函数和 Lambda
Section titled “高阶函数和 Lambda”高阶函数是接受另一个函数作为参数或返回一个函数的函数。这是函数式编程的基石。
可以使用 lambda 特殊形式动态创建匿名(无名)函数。
示例:使用 mapcar 和 lambda
Section titled “示例:使用 mapcar 和 lambda”mapcar 是一个经典的高阶函数。它将给定函数应用于列表的每个元素,并返回一个包含结果的新列表。
;; 定义一个数字列表(defparameter *numbers* '(1 2 3 4 5))
;; 使用 mapcar 和具名函数 (sqrt)(print (mapcar #'sqrt *numbers*))
;; 使用 mapcar 和匿名 lambda 函数来求每个数的平方(print (mapcar (lambda (x) (* x x)) *numbers*))(1.0 1.4142135 1.7320508 2.0 2.236068)(1 4 9 16 25)#'sqrt:#'(尖引号)语法是(function sqrt)的简写。它获取与符号sqrt相关联的函数对象。(lambda (x) (* x x)):创建一个接受一个参数x并返回其平方的函数。这个函数对象直接传递给mapcar。