【问题标题】:lisp error: should be lambda expressionlisp 错误:应该是 lambda 表达式
【发布时间】:2014-07-07 22:42:40
【问题描述】:

我正在自己学习 lisp,但我无法弄清楚为什么会出现此错误。 如果有人可以帮助我,那就太好了:)

这是我收到错误的情况:

(cond ((equal c1 caracter) (push caracter pilatemp))
    ((or (equal c2 caracter) (equal c3 caracter) (equal c4 caracter) (equal c5 caracter) (equal c6 caracter))
        ((loop
            (setf t1 (jerarquia(caracter)))
            (setf t2 (jerarquia(first pilatemp)))
            if((or (= t1 t2) (> t1 t2)) (return))
            (push (pop pilatemp) piladef))
        (push caracter pilatemp)
            ))
    ((equal c7 caracter) ((loop
                    if((equal (first pila) c1) (return))
                    (push (pop pilatemp) piladef))
                (pop pilatemp)))
    (T (push caracter piladef))
)

这里是“jerarquia”函数:

(defun jerarquia(x)
(setf c1 ")")
(setf c2 "+")
(setf c3 "-")
(setf c4 "^")
(setf c5 "*")
(setf c6 "/")
(setf c7 "(")
(cond ((equal c1 x) 5)
    ((equal c4 x) 4)
    ((equal c5 x) 3)
    ((equal c2 x) 2)
    ((equal c7 x) 1)
    (T 0)))

这是我得到的错误:

*** - SYSTEM::%EXPAND-FORM:
(LOOP (SETF T1 (JERARQUIA (CARACTER)))
  (SETF T2 (JERARQUIA (FIRST PILATEMP))) IF
  ((OR (= T1 T2) (> T1 T2)) (RETURN)) (PUSH (POP PILATEMP) PILADEF))
should be lambda expression

【问题讨论】:

  • (jerarquia caracter), not (jerarquia(caracter)) ... 函数的参数没有额外的括号。
  • 你是对的,谢谢,但仍然遇到同样的错误:/
  • 为什么LOOP前面有双括号?
  • 我写了双括号,因为我希望 (push caracter pilatemp) 在第二个条件的 内,而不是在循环内。我不知道这是否可以:/
  • Common lisp error: "should be lambda expression" 的可能重复项请注意,该重复项是在 Google 上搜索"should be lambda expression" site:stackoverflow.com第一个结果。

标签: lisp common-lisp


【解决方案1】:

很明显,您对如何将 SExpressions 组合在一起以创建有效的 Common Lisp 程序感到非常困惑。这对初学者来说很常见。让我试着给你一个非常简短的介绍。

最简单的就是原子。诸如 Alpha、+、12、-23.4 之类的东西;这四个分别是两个符号,两个数字。加号是一个符号,就像 alpha 一样。

下一个最简单的事情是函数调用,即调用一个函数。例如:(+ 1 2)。该示例中的函数是加法,它与符号 + 相关联。

函数调用在所有编程语言中都很常见。通常他们从左到右自下而上评估它们。所以 (F (G 1 2) (H 3 5)) 将调用 G,然后是 H,然后是 F。如果他们想做其他事情,他们会引入语法,如 if 语句、循环等。

这给我们带来了下一件事,一件聪明的事情。在 Lisp 中,所有语法乍一看就像函数调用一样。所以你会得到类似的东西:(如果(

这些自上而下的形式有两种形式,特殊形式和宏,但对于初学者来说并不重要。使用这些形式代替您在其他语言中找到的语法。评估器/编译器会查看列表中的第一个术语,以确定它是简单的函数调用还是一些语法。

这让我们可以解释您在发帖中观察到的错误。求值者(或编译器)看到 ((loop ...) ...),其中的第一项是 (loop ...)。这让评估者感到困惑。它期望看到一个符号。当然,错误消息是完全不透明的,但那是因为事情比我想象的要微妙一些。对于初学者来说并不重要。

表单 (cond ...) 是表单的另一个示例,它不是简单的函数调用,而是更像语法。当它作为第一个元素,即 cond 时,它知道期望 (cond (??? ...) (??? ...) ...etc...) 在哪里 ???是用于决定是否应该运行该分支的表单...

您的代码还有许多其他问题。我建议您获得一个 lisp REPL 并以小得多的部分进行实验。循环坏了。 "((OR (...") 遇到第一种形式不是符号的相同问题。看来您的调用字符串包含单个字符“字符”而不是字符串,这很俗气但可以容忍。

【讨论】:

  • 非常感谢,现在我对 Lisp 有了更多的了解,并且我已经重组了我的程序 :)
【解决方案2】:

Lisp 与大多数其他语言的不同之处在于括号很重要

具体来说,(foo)foo((foo)) 不同。

当你写(JERARQUIA (CARACTER))时,lisp认为你要在函数CARACTER的返回值上调用JERARQUIA,而不是变量CARACTER的值。

同样,当您编写 ((loop ...) ...) 时,lisp 必须将 (loop ...) 解释为函数指示符,它可以是符号或 lambda 表达式(或 (setf ...))。

因此,为避免此错误,您需要做的就是删除多余的一组括号,将 ((loop ...)) 替换为 (loop ...)

【讨论】:

  • 我写了双括号,因为我希望 (push caracter pilatemp) 在第二个条件的 内,而不是在循环内。我只写一个括号也没关系?
  • 正如我所说,foo(foo)((foo)) 是非常不同的东西。请删除多余的括号。
  • 使用 emacs 正确格式化您的代码。这将为您查明错误,甚至无需在 Lisp 中评估它
  • @user3654129 Common Lisp 要求您正确填写括号。这与您可能习惯的其他语言不同。括号改变程序的含义。您无法添加或删除它们,因为您喜欢它。它们绝不是可选的或毫无意义的。
  • 如果您想在cond 中包含多个“动作”,您可以将它们包装在(PROGN ...) 中,但恰好cond 有一个“隐式progn” ,因此在这种特定情况下,progn 的额外包装不会做任何事情。
猜你喜欢
  • 2015-12-20
  • 2011-02-04
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-01-12
  • 1970-01-01
相关资源
最近更新 更多