2014-10-01 70 views
0

我剛開始玩弄Lisp的(共Lisp的),這裏的計算數字申請#「或不適用#」

CL-USER> (defun average (list) (/ (apply #'+ list) (length list))) 
AVERAGE 
CL-USER> (average '(1 2 3 4)) 
5/2 

但是如果名單的平均值的函數我重寫像這樣

CL-USER> (defun average (list) (/ (+ list) (length list))) 

它不會因爲(+「(列表的號碼))無法評估,長度因此arguement並在+的表達是不兼容的工作的功能。

是否有一種cajoling(list)方法可以用+作爲表達式自然地進行評估,並作爲數據傳遞給length?而不是使用應用#」

我已經試過這樣:

(defun average (list) (/ (+ list) (length '(list)))) 

,但這似乎並沒有任何做吧!

+1

有你希望能夠做到這一點實際的原因是什麼?我認爲你的問題是語法(函數(arg1 arg2))在某種程度上比(函數arg1 arg2)更「自然」。 – 2014-10-02 01:33:19

+1

沒理由,我只是想明白!不過,(函數arg1 arg2)看起來更加「自然」(高度主觀的!無可否認),在我看來,操作函數如何看待參數會更「自然」,而不是「超越騎乘「函數(用尖銳的引用)來適應參數。如果你明白我的意思。由於引用(列表)繞過了默認的評估規則,我只是想知道是否有一些「反向」的引用,我錯過了某處。 – trev66 2014-10-02 11:28:08

回答

5

參見Common lisp: How many argument can a function take?

這將是優選使用(reduce #'+ list)代替(apply #'+ list)因爲apply受到爭論一個該函數可以採取的數目的限制。

所以,你應該平均函數如下:

(defun average (list) 
    (/ (reduce #'+ list) 
    (length list))) 

BTW,代碼(length '(list))返回1,因爲它返回一個包含符號「清單」列表的lenght。

+0

好酷,非常感謝 – trev66 2014-10-02 11:29:27

3

沒有理由不使用APPLY或更好,REDUCE。這裏REDUCE是正確的功能。

如果你在Lisp中編程,大多數時候你必須使用一個符號,命名你的操作,然後是參數。這是Lisp中的一般基本表達風格。你可能會希望有更簡單的方法來寫一些東西,比如用函數來減少列表。但是在基本的Lisp中沒有。

(+ (list 1 2 3 4))是錯誤,因爲+需要數字,而不是列表。

如果你想總結列表中的所有數字,你必須使用REDUCE。該操作也被稱爲摺疊

在列表中總結的數字:

(reduce #'+ (list 1 2 3 4)) 

另一種簡單的方法是使用LOOP

(loop for n in (list 1 2 3 4) sum n) 

寫東西像(length '(list))是沒有意義的,因爲你是引用列表。引用列表被視爲數據而不是代碼。由於它是不變的數據,結果總是1

其中一個Lisp方法是建立一個詞彙表可重複使用的函數。一個不使用最短的符號,而是使用明顯的名稱創建可重用的函數。因此,如果我們總和了很多,我們寫了一個sum功能:

(defun sum (list) 
    (reduce #'+ list)) 

然後average是:

(defun average (list) 
    (/ (sum list) (length list))) 
+0

好的謝謝,非常感謝。 – trev66 2014-10-02 11:32:40