我从较大的脚本中隔离了此功能,并通过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)))
错误有时是The variable LEFT-BANK-MISSIONARIES is unbound.unmatched close parenthesis
或syntax error near unexpected token
('`。在此版本的函数中,错误是后者。
在Common Lisp中,有两种形式的本地声明(let
):
(let ((var1 exp1)
(var2 exp2)
...
(varn expn))
exp)
和
(let* ((var1 exp1)
(var2 exp2)
...
(varn expn))
exp)
首先,每个表达式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))))
请注意,如果要返回if
,则最后的generalized boolean是无用的。