LISP - 函数
函数是一组一起执行任务的语句。
可以把代码放到单独的函数。如何划分代码之前不同的功能,但在逻辑上划分通常是这样每个函数执行特定的任务。
LISP函数定义
命名函数defun宏用于定义函数。该函数的defun宏需要三个参数:
-
函数名称
-
函数的参数
-
函数的体
defun语法是:
(defun name (parameter-list) "Optional documentation string." body)
让我们举例说明概念,简单的例子。
例子 1
让我们编写了一个名为averagenum,将打印四个数字的平均值的函数。我们将会把这些数字作为参数。
创建一个名为main.lisp一个新的源代码文件,并在其中输入如下代码:
(defun averagenum (n1 n2 n3 n4) (/ ( + n1 n2 n3 n4) 4)) (write(averagenum 10 20 30 40))
当执行的代码,它返回以下结果:
25
示例 2
让我们定义和调用函数,将计算出的圆的面积,圆的半径被指定作为参数的函数。
创建一个名为main.lisp一个新的源代码文件,并在其中输入如下代码:
(defun area-circle(rad) "Calculates area of a circle with given radius" (terpri) (format t "Radius: ~5f" rad) (format t "~%Area: ~10f" (* 3.141592 rad rad))) (area-circle 10)
当执行的代码,它返回以下结果:
请注意:
-
可以提供一个空的列表作为参数,这意味着函数没有参数,该列表是空的,表示为()。
-
LISP还允许可选,多个和关键字参数。
-
文档字符串描述了函数的目的。它与函数名相关联,并且可以使用文档函数来获得。
-
函数的主体可以包含任意数量的Lisp表达式。
-
在主体内的最后一个表达式的值返回函数的值。
-
还可以使用返回 - 从特殊的运算符函数返回一个值。
让我们讨论在简要上述概念。点击以下链接,了解详细信息:
可选参数
可以使用可选参数定义一个函数。要做到这一点,需要把符号与可选的可选参数的名称之前。
我们将只是显示它接收的参数的函数。
示例
创建一个名为main.lisp一个新的源代码文件,并在其中输入如下代码:
(defun show-members (a b &optional c d) (write (list a b c d))) (show-members 1 2 3) (terpri) (show-members 'a 'b 'c 'd) (terpri) (show-members 'a 'b) (terpri) (show-members 1 2 3 4)
当执行代码,它返回以下结果:
(1 2 3 NIL) (A B C D) (A B NIL NIL) (1 2 3 4)
请注意,参数c和d是在上面的例子中,是可选参数。
其余部分参数
有些函数需要采用可变数目的参数。
例如,我们使用格式化函数需要两个必需的参数,数据流和控制字符串。然而,该字符串后,它需要一个可变数目的取决于要显示的字符串中的值的数目的参数。
同样,+ 函数,或 * 函数也可以采取一个可变数目的参数。
可以提供这种可变数目的使用符号与其余参数。
下面的例子说明了这个概念:
示例
创建一个名为main.lisp一个新的源代码文件,并在其中输入如下代码:
(defun show-members (a b &rest values) (write (list a b values))) (show-members 1 2 3) (terpri) (show-members 'a 'b 'c 'd) (terpri) (show-members 'a 'b) (terpri) (show-members 1 2 3 4) (terpri) (show-members 1 2 3 4 5 6 7 8 9)
当执行代码,它返回以下结果:
(1 2 (3)) (A B (C D)) (A B NIL) (1 2 (3 4)) (1 2 (3 4 5 6 7 8 9))
关键字参数
关键字参数允许指定哪个值与特定的参数。
它使用的是 &key 符号表示。
当发送的值到该函数必须先于值 :parameter-name.
下面的例子说明了这个概念。
例子
创建一个名为main.lisp一个新的源代码文件,并在其中输入如下代码:
(defun show-members (&key a b c d ) (write (list a b c d))) (show-members :a 1 :c 2 :d 3) (terpri) (show-members :a 'p :b 'q :c 'r :d 's) (terpri) (show-members :a 'p :d 'q) (terpri) (show-members :a 1 :b 2)
当执行代码,它返回以下结果:
(1 NIL 2 3) (P Q R S) (P NIL NIL Q) (1 2 NIL NIL)
从函数返回的值
默认情况下,在LISP函数返回最后一个表达式作为返回值的值。下面的例子将证明这一点。
示例 1
创建一个名为main.lisp一个新的源代码文件,并在其中输入如下代码:
(defun add-all(a b c d) (+ a b c d)) (setq sum (add-all 10 20 30 40)) (write sum) (terpri) (write (add-all 23.4 56.7 34.9 10.0))
当执行代码,它返回以下结果:
100 125.0
但是,可以使用返回- 从特殊的操作符立即从函数返回任何值。
示例 2
创建一个名为main.lisp一个新的源代码文件,并在其中输入如下代码:
(defun myfunc (num) (return-from myfunc 10) num) (write (myfunc 20))
当执行代码,它返回以下结果:
10
更改一点点代码:
(defun myfunc (num) (return-from myfunc 10) write num) (write (myfunc 20))
它仍然返回:
10
lambda函数
有时,可能需要一个函数只在一个程序中的位置和功能是如此的微不足道,可能不给它一个名称,也可以不喜欢它存储在符号表中,宁可写一个未命名或匿名函数。
LISP允许编写评估计算在程序中遇到的匿名函数。这些函数被称为Lambda函数。
可以使用lambda表达式创建这样的功能。lambda表达式语法如下:
(lambda (parameters) body)
lambda形式可以不进行评估计算,它必须出现只有在LISP希望找到一个函数。
示例
创建一个名为main.lisp一个新的源代码文件,并在其中输入如下代码:
(write ((lambda (a b c x) (+ (* a (* x x)) (* b x) c)) 4 2 9 3))
当执行代码,它返回以下结果:
51
映射函数
映射函数是一组函数,可以连续地施加于元件中的一个或多个列表。应用这些功能列表的结果被放置在一个新的列表,而新的列表返回。
例如,mapcar函数处理的一个或多个列表连续元素。
在mapcar函数的第一个参数应该是一个函数,其余的参数是该函数的应用列表(次)。
函数的参数被施加到连续的元素,结果为一个新构造的列表。如果参数列表是不相等的长度,然后映射的过程停止在达到最短的列表的末尾。结果列表将元素作为最短输入列表的数目相同。
示例 1
让我们从一个简单的例子和数字1 添加到每个列表的元素( 23 34 45 56 67 78 89)。
创建一个名为main.lisp一个新的源代码文件,并在其中输入如下代码:
(write (mapcar '1+ '(23 34 45 56 67 78 89)))
当执行代码,它返回以下结果:
(24 35 46 57 68 79 90)
示例 2
让我们写这将多维数据集列表中的元素的函数。让我们用一个lambda函数用于计算数字的立方。
创建一个名为main.lisp一个新的源代码文件,并在其中输入如下代码:
(defun cubeMylist(lst) (mapcar #'(lambda(x) (* x x x)) lst)) (write (cubeMylist '(2 3 4 5 6 7 8 9)))
当执行代码,它返回以下结果:
(8 27 64 125 216 343 512 729)
示例 3
创建一个名为main.lisp一个新的源代码文件,并在其中输入如下代码:
(write (mapcar '+ '(1 3 5 7 9 11 13) '( 2 4 6 8)))
当执行代码,它返回以下结果:
(3 7 11 15)