如何处理常见的lisp中的“& rest”args

时间:2017-02-14 06:26:30

标签: common-lisp

我是普通lisp的新手,当我在函数参数声明中看到&rest时,我认为它与*args中的ruby类似。我开始编写一个函数sumit来执行与+相同的操作。

(defun sumit (&rest args)
  (if (null args)
      0
      (+ (car args) (sumit (cdr args)))))

但是当我调用(sumit 1 2 3)时会出现分段错误,递归永远不会结束。 (sumit)虽然有效。

所以我的嫌疑人是(null args)部分,但在更改类似(eql nil args)之类的东西后,或类似的东西不起作用。

那么分解&rest args的正确方法是什么?检查nil的正确方法是什么?

1 个答案:

答案 0 :(得分:3)

(sumit (cdr args))在一个参数上调用sumit - 一个列表。 您需要使用apply

(defun sumit (&rest args)
  (if args
      (+ (car args) (apply #'sumit (cdr args)))
      0))

注意:

  1. 此实现不是尾递归的(而ANSI CL 需要尾调用优化,许多实现提供它)。
  2. 看看call-arguments-limitlambda-parameters-limit
  3. 要对列表中的元素求和,可以使用(apply #'+ list-of-numbers), 但是,由于以上两个变量, (reduce #'+ list-of-numbers) 是一个更好的方法。