我刚刚开始使用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)
但这似乎也没有做到!
最好使用(reduce #'+ list)
替代,(apply #'+ list)
因为apply
它受到该函数可以采用的参数个数的限制.
所以你的平均功能应该是这样的:
(defun average (list)
(/ (reduce #'+ list)
(length list)))
Run Code Online (Sandbox Code Playgroud)
顺便说一句,代码(length '(list))
返回1,因为它返回包含符号 "list" 的列表的长度.
没有理由不使用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)
归档时间: |
|
查看次数: |
124 次 |
最近记录: |