常见的lisp错误:“应该是lambda表达式”

时间:2010-04-04 20:44:36

标签: syntax-error lisp common-lisp

我刚刚开始学习Common Lisp,我正在尝试构建一个将数字插入树中的函数。我收到了一个错误,

  

*** - SYSTEM ::%EXPAND-FORM :( CONS NIL LST)应该是lambda表达式

从谷歌搜索,似乎这种情况发生在你有太多的括号,但看了一个小时左右并改变了一切,我无法弄清楚我可以做到这一点。 / p>

这是正在发生的代码:

(defun insert (lst probe)
    (cond ((null lst) (cons probe lst))
        ((equal (length lst) 1)
            (if (<= probe (first lst))
                (cons probe lst)
                (append lst (list probe))))
        ((equal (length lst) 2)
            ((cons nil lst) (append lst nil) (insertat nil lst 3)
                (cond ((<= probe (second lst)) (insert (first lst) probe))
                     ((> probe (fourth lst)) (insert (fifth lst) probe))
                     (t (insert (third lst) probe)))))))

我很确定它发生在((等于(长度为lst)2)之后,其中的想法是将空列表插入到现有列表中,然后在末尾附加一个空列表,然后插入一个空列表进入中间。

4 个答案:

答案 0 :(得分:7)

如果你正确缩进函数,那么你可以看到CONS NIL LST前面有一个额外的括号。

(defun insert (lst probe)
  (cond ((null lst) (cons probe lst))
        ((equal (length lst) 1)
         (if (<= probe (first lst))
             (cons probe lst)
           (append lst (list probe))))
        ((equal (length lst) 2)
         ((cons nil lst) (append lst nil) (insertat nil lst 3)
          (cond ((<= probe (second lst)) (insert (first lst) probe))
                ((> probe (fourth lst)) (insert (fifth lst) probe))
                (t (insert (third lst) probe)))))))

在大多数Lisp IDE中,您可以缩进表达式。在LispWorks中,选择整个表达式并执行m-x缩进区域。

答案 1 :(得分:6)

正确!问题出现在那之后,它说的是

((cons nil lst) (append lst nil) (insertat nil lst 3) ...

问题是两个开头的括号。括号可以在特殊上下文中改变含义(例如您正在使用的cond形式),但在此上下文中,括号表示常规函数应用程序,就像您可能习惯的那样。这意味着括号后的第一件事必须是函数。从外部括号的角度来看,首先是(cons nil lst),所以它必须是一个函数(它不是)。

请注意,您不能只删除括号,因为cons函数会返回您想要的新列表,但不会更改旧列表。你可能想要这样的东西:

(setq lst (cons nil lst))
(setq lst (append lst nil))
(setq lst (insertat nil lst 3))
...

答案 2 :(得分:2)

要修复即时错误,您可以在之前添加PROGN(CONS NIL ...)。 PROGN通过评估其中的每个表单并将其中的最后一个表单的值作为其值返回来工作。

然而,你的程序仍然不会做你认为它做的事情(我猜是这样)。你知道,在Common Lisp中你使用第一个cons对象来表示整个非空列表,你不能简单地替换头部缺点。更好的方法是将新列表作为函数的值返回。

(defun insert (lst probe)
  (ecase (length lst)
    (0 (list probe))
    (1 (let ((c (first lst)))
         (if (<= probe c)
             (list probe c)
             (list c probe))))
    (2 (cond
         ((<= probe (first lst)) 
          (list probe (first lst) nil (second lst) nil))
         ((> probe (second lst))
          (list nil (first lst) nil (second lst) probe))
         (t
          (list nil (first lst) probe (second lst) nil))))))

使用此功能时,可能需要(setf lst (insert lst [some-number]))

答案 3 :(得分:1)

你是对的;在标记为“error is here”的行中,存在语法错误:

(defun insert (lst probe)
  (cond ((null lst) (cons probe lst))
        ((equal (length lst) 1)
         (if (<= probe (first lst))
             (cons probe lst)
             (append lst (list probe))))
        ((equal (length lst) 2)
         (#|Error is here|# (cons nil lst) (append lst nil) (insertat nil lst 3)
          (cond ((<= probe (second lst)) (insert (first lst) probe))
                ((> probe (fourth lst)) (insert (fifth lst) probe))
                (t (insert (third lst) probe)))))))

对于编译器/解释器,表单读作函数调用“函数”(cons nil list),它根本不是函数。编译器在这里抱怨在“运算符”位置使用复合形式,这不是lambda(在该位置接受的唯一一种复合形式。)

((cons nil lst)                         #| <-- Form in operator position |#
 (append lst nil)                       #| <-- First argument form |#
 (insertat nil lst 3)                   #| <-- Second argument form |#
 (cond ((<= probe (second lst)) (insert (first lst) probe)) #| Third argument |#
       ((> probe (fourth lst)) (insert (fifth lst) probe))
       (t (insert (third lst) probe))))

我帮助重新制定表达方式,但我不确定你想在这里完成什么。