【问题标题】:Difference between &rest parameter and list in Common LispCommon Lisp中&rest参数和列表的区别
【发布时间】:2013-04-02 22:01:04
【问题描述】:
(defun highest (lat)
    (cond
        ((null lat) nil)
        ((null (cdr lat)) (car lat))
        (T (higher (car lat) (highest (cdr lat))))))

(defun higher (a1 a2)
    (cond
        ((> a1 a2) a1)
        (T a2)))

此功能按预期工作:

> (highest '(3 5 1 2 3))    
3. Trace: (HIGHEST '(3 5 1 2 3))
4. Trace: (HIGHEST '(5 1 2 3))
5. Trace: (HIGHEST '(1 2 3))
6. Trace: (HIGHEST '(2 3))
7. Trace: (HIGHEST '(3))
7. Trace: HIGHEST ==> 3    
6. Trace: HIGHEST ==> 3
5. Trace: HIGHEST ==> 3
4. Trace: HIGHEST ==> 5    
3. Trace: HIGHEST ==> 5

但是如果我把参数改成&rest:

(defun highest (&rest args)
    (cond
        ((null args) nil)
        ((null (cdr args)) (car args))
        (T (higher (car args) (highest (cdr args))))))

它的行为不一样。

> (highest 3 5 1 2 3)
3. Trace: (HIGHEST '3 '5 '1 '2 '3)
4. Trace: (HIGHEST '(5 1 2 3))
4. Trace: HIGHEST ==> (5 1 2 3)
*** - >: (5 1 2 3) is not a real number

编辑:对不起,我忘了提到在第二种情况下我将参数传递给原子。我编辑了问题以使其更清楚。

【问题讨论】:

    标签: lisp common-lisp


    【解决方案1】:

    在调用(最高 3 2 10)之前尝试评估(跟踪最高)。然后,您将看到第二个调用如下所示: (最高'(2 10)) 然后 &rest 参数会看到一个恰好是列表的对象。

    要更正此问题,请使用应用。 APPLY 类似于​​ funcall,但它的最后一个参数必须是一个列表,并且被视为“拼接到”函数调用上。像这样: (应用#'highest (cdr args))

    【讨论】:

      【解决方案2】:

      &rest 表单收集作为列表本身传递的所有其余参数。在highest (&rest args) 的情况下,args 实际上是一个带有元素的列表,一个列表。也就是说,在调用中,args 的值为((3 2 10))

      带有&rest 修饰符的highest 的第二个版本总是进入条件的第二个测试,因为args 只是一个包含一个元素的列表(恰好是一个列表)。您返回args 的第一个元素,即列表本身,(3 2 10)

      这两种构造的不同之处在于,在第一个版本中,您将列表作为参数传递,函数接收列表作为函数的唯一参数。在&rest 的情况下,所有参数(在这种情况下只有一个)被收集到一个列表中(在这种情况下只有一个元素)。

      编辑:根据您的编辑,正如 Thomas 在他的评论中所说,使用 &rest 意味着您必须使用 apply 递归调用。这是正确的实现:

      (defun highest (&rest args)
          (cond
              ((null args) nil)
              ((null (cdr args)) (car args))
              (T (higher (car args) (apply #'highest (cdr args))))))
      

      (注意最后一行的apply)。

      【讨论】:

        猜你喜欢
        • 2019-08-03
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2014-06-11
        • 1970-01-01
        • 2016-02-18
        • 2013-06-24
        相关资源
        最近更新 更多