位置:首頁 > 高級語言 > 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)