为什么这个简单的 LISP 函数会抛出错误?

bri*_*akh 1 lisp clisp common-lisp syntax-error

我将这个函数从一个更大的脚本中分离出来,并通过https://www.jdoodle.com/execute-clisp-online/运行它。即使抛出了一个错误,它似乎也遵循 LISP 的规则,除非我遗漏了一些明显的东西。

(defun cannibals-can-eat (state start-state)
    (let ((left-bank-missionaries 2)
         (left-bank-cannibals 5)
         (right-bank-missionaries (- 3 left-bank-missionaries))
         (right-bank-cannibals (- 2 left-bank-cannibals)))

         (if (or (> left-bank-cannibals left-bank-missionaries)
                 (> right-bank-cannibals right-bank-missionaries))
             t
             nil)))
Run Code Online (Sandbox Code Playgroud)

错误有时是The variable LEFT-BANK-MISSIONARIES is unbound.unmatched close parenthesissyntax error near unexpected token('`。使用此版本的函数,错误是后者。

Ren*_*nzo 5

在 Common Lisp 中有两种形式的局部声明 ( let):

(let ((var1 exp1)
      (var2 exp2)
      ...
      (varn expn))
  exp)
Run Code Online (Sandbox Code Playgroud)

(let* ((var1 exp1)
       (var2 exp2)
       ...
       (varn expn))
  exp)
Run Code Online (Sandbox Code Playgroud)

在第一个中,每个表达式expi都在let. 在第二个表达式expi中,在包含所有先前声明的环境中计算每个表达式var1 ... var(i-1)

因此,在您的示例中,right-bank-missionaries使用声明left-bank-missionaries未定义,因为它是在同一个let.

简单地用于let*允许在声明后立即使用每个变量:

(defun cannibals-can-eat (state start-state)
    (let* ((left-bank-missionaries 2)
           (left-bank-cannibals 5)
           (right-bank-missionaries (- 3 left-bank-missionaries))
           (right-bank-cannibals (- 2 left-bank-cannibals)))

      (or (> left-bank-cannibals left-bank-missionaries)
          (> right-bank-cannibals right-bank-missionaries))))
Run Code Online (Sandbox Code Playgroud)

请注意,if如果您想返回一个通用的 boolean,则 final是无用的。