2014-10-01 71 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