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)