位置:首页 > 高级语言 > Lisp在线教程 > LISP - 函数

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)