【问题标题】:to apply #' or not to apply #'申请#'或不申请#'
【发布时间】:2014-10-01 23:58:51
【问题描述】:

我刚开始玩 Lisp (Common-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)))

它不起作用,因为 (+ '(list-of-numbers)) 无法评估,因此长度的争论和 + 中的表达式不兼容。

有没有一种哄骗(列表)的方法可以自然地被 + 评估为表达式并作为数据传递给 length ?而不是使用 apply #'

我试过这个:

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

但这似乎也不行!

【问题讨论】:

  • 您是否有实际的理由希望能够做到这一点?我认为您的问题是语法 (function (arg1 arg2)) 在某种程度上比 (function arg1 arg2) 更“自然”。
  • 没有理由,我只是想明白!再次不, (function arg1 arg2) 似乎更“自然”(非常主观!诚然),在我看来,对函数如何看待 args 而不是“过度骑行”进行操作会更“自然” " 适合 args 的函数(带有尖引号)。如果你明白我的意思。由于quote(list) 绕过了默认的评估规则,我只是想知道是否有一些我在某处遗漏的引用的“逆”。

标签: lisp common-lisp


【解决方案1】:

Common lisp: How many argument can a function take?

最好使用(reduce #'+ list) 而不是(apply #'+ list),因为apply 受该函数可以采用的参数数量的限制。

所以你的平均函数应该是这样的:

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

顺便说一句,代码(length '(list)) 返回 1,因为它返回包含 symbol “列表”的列表的长度。

【讨论】:

    【解决方案2】:

    没有理由不使用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 很多,我们会编写一个 sum 函数:

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

    那么average就是:

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

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2017-05-17
      • 2013-02-23
      • 2011-08-31
      相关资源
      最近更新 更多