申请#'或不申请#'

0 lisp common-lisp

我刚刚开始使用Lisp(Common-Lisp),这是一个计算数字列表平均值的函数

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

但是,如果我重写这样的功能

CL-USER> (defun average (list) (/ (+ list) (length list)))
Run Code Online (Sandbox Code Playgroud)

它不起作用,因为(+'(数字列表))无法被评估,因此长度的争论和+中的表达是不相容的.

有没有一种方法可以将cajoling(list)自然地作为表达式进行评估+并作为数据传递给长度?而不是使用申请#'

我试过这个:

(defun average (list) (/ (+ list) (length '(list))))
Run Code Online (Sandbox Code Playgroud)

但这似乎也没有做到!

fst*_*our 5

请参阅Common lisp:函数可以使用多少个参数?

最好使用(reduce #'+ list)替代,(apply #'+ list)因为apply它受到该函数可以采用的参数个数的限制.

所以你的平均功能应该是这样的:

(defun average (list)
  (/ (reduce #'+ list)
     (length list)))
Run Code Online (Sandbox Code Playgroud)

顺便说一句,代码(length '(list))返回1,因为它返回包含符号 "list" 的列表的长度.


Rai*_*wig 5

没有理由不使用APPLY,或者更好的是,REDUCE. 这REDUCE是正确的函数。

如果你用 Lisp 编程,大多数时候你必须使用符号来命名你的操作,后跟参数。这是Lisp中一般的基本表达风格。您可能期望有更短的方法来编写诸如使用函数减少列表之类的内容。但在基本的 Lisp 中没有。

(+ (list 1 2 3 4))是一个错误,因为+需要数字,而不是列表。

如果您想对列表中的所有数字求和,则必须使用REDUCE. 此操作也称为折叠

对列表中的数字求和:

(reduce #'+ (list 1 2 3 4))
Run Code Online (Sandbox Code Playgroud)

另一种简单的方法是使用LOOP

(loop for n in (list 1 2 3 4) sum n)
Run Code Online (Sandbox Code Playgroud)

写这样的东西(length '(list))是没有意义的,因为你引用的是一个列表。引用的列表被视为数据而不是代码。由于它是常量数据,因此结果始终为1

Lisp 实现短程序的方法之一是建立可重用函数的词汇表。人们不使用最短的符号,而是创建具有明显名称的可重用函数。因此,如果我们求和很多,我们就写一个sum函数:

(defun sum (list)
  (reduce #'+ list))
Run Code Online (Sandbox Code Playgroud)

那么average就是:

(defun average (list)
  (/ (sum list) (length list)))
Run Code Online (Sandbox Code Playgroud)