在 Common Lisp 中,要定義全域函式可以使用defun運算式。
這個運算式的第一個引數是參數的陣列(空的陣列代表這個函式沒有參數)。
接著是選用的文件字串(見下文),然後是零個或多個運算式,組成函式的「主體」。
函式可以有零個或多個參數。
(defun no-args () (+ 1 1))
(defun add-one (x) (1+ x))
(defun add-nums (x y) (+ x y))
呼叫函式的方式是求值一個運算式:把代表該函式的符號放在運算式的第一個元素,函式的引數(如果有的話)則放在運算式中其餘的位置。
函式求值後所得到的值,就是函式主體中最後被求值的那個運算式的值。 所有函式都會求值出一個值。
(add-nums 2 2) ;; => 4
函式也可以選擇性地帶有一個文件字串(也稱作「docstring」)。
如果有的話,它會放在引數的陣列之後、函式主體之前。
你可以透過documentation取得文件字串。
(defun add-nums (x y) "Add X and Y together" (+ x y))
(documentation 'add-nums 'function) ;; => "Add X and Y together"
;; Note that if one provides a docstring but fails to provide a body
;; then the docstring is interpreted by Common Lisp as the body, not
;; the docstring
(defun no-body ())
(no-body) ;; => NIL
(defun mistake () "This is not a docstring")
(mistake) ;; => "This is not a docstring"
(documentation 'mistake 'function) ;; => NIL
Lisp 外星人 Lilly 回來了,這次要做更多料理!他們這次要製作 Lisp 外星千層麵,這道菜跟人類的千層麵其實沒差多少。
Lilly 會需要一些函式,來協助算出千層麵的烹調時間。而且每個函式都要有完善的說明文件,這樣 Lilly 才不會忘記每個函式的用途。
你能幫 Lilly 寫幾個函式,協助他們掌握千層麵的烹調時間嗎?
定義expected-time-in-oven函式,它不接受任何參數,並回傳千層麵應該待在烤箱裡幾分鐘。依照 Lisp 外星人的傳統(就像 Lilly 的親代單位以前做菜那樣),預期的烤箱時間為 337 分鐘:
(expected-time-in-oven) ;; => 337
定義remaining-minutes-in-oven函式,它接受千層麵已經待在烤箱裡的實際分鐘數作為參數,並根據上一個任務算出的預期烤箱時間,回傳千層麵還需要在烤箱裡待幾分鐘。
(remaining-minutes-in-oven 100) ;; => 237
定義preparation-time-in-minutes函式,它接受 Lilly 加進千層麵的層數作為參數,並回傳 Lilly 花了幾分鐘準備千層麵,假設每一層需要 19 分鐘準備。
(preparation-time-in-minutes 3) ;; => 57
定義elapsed-time-in-minutes函式,它接受兩個參數:第一個參數是 Lilly 加進千層麵的層數,第二個參數是千層麵已經待在烤箱裡的分鐘數。這個函式應該回傳 Lilly 總共花了幾分鐘烹調千層麵,也就是準備時間的分鐘數,加上千層麵當下已經待在烤箱裡的分鐘數。
(elapsed-time-in-minutes 3 100) ;; => 157