【问题标题】:Common lisp error: "should be lambda expression"常见的 lisp 错误:“应该是 lambda 表达式”
【发布时间】:2011-02-04 06:31:25
【问题描述】:

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

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

通过谷歌搜索,似乎当你有太多括号时会发生这种情况,但是在看了一个小时左右并改变了一些东西之后,我不知道我可以在哪里做这个。

这是发生的代码:

(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)))))))

我很确定它发生在 ((equal (length lst) 2) 之后,其想法是在现有列表中插入一个空列表,然后在末尾附加一个空列表,然后插入一个空列表到中间。

【问题讨论】:

    标签: syntax-error lisp common-lisp


    【解决方案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))))
    

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

    【讨论】:

      【解决方案2】:

      正确!问题就在那之后的那一行,它说

      ((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))
      ...
      

      【讨论】:

      • 我相信你是对的 - 我忘了 cons 实际上并没有修改列表。
      【解决方案3】:

      如果你正确缩进函数,那么你可以看到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 Indent Region。

      【讨论】:

        【解决方案4】:

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

        但是,您的程序仍然不会做您认为它会做的事情(我猜是这样)。你知道,在 Common Lisp 中你使用第一个 cons 对象来表示整个非空列表,你不能简单地替换 head 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]))当你使用这个功能。

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2014-07-07
          • 2015-12-20
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2015-01-12
          • 1970-01-01
          相关资源
          最近更新 更多