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)