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表達式。

  • 在主體內的最後一個表達式的值返回函數的值。

  • 還可以使用返回 - 從特殊的運算符函數返回一個值。

讓我們討論在簡要上述概念。點擊以下鏈接,瞭解詳細信息:

  • 可選參數

  • 其餘部分參數

  • 關鍵字參數

  • 從函數返回的值

  • lambda函數

  • 映射函數

可選參數

可以使用可選參數定義一個函數。要做到這一點,需要把符號與可選的可選參數的名稱之前。

我們將只是顯示它接收的參數的函數。

示例

創建一個名爲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)