I isolated this function from a larger script and ran it through https://www.jdoodle.com/execute-clisp-online/. Even though there is an error thrown, it seems to follow the rules of LISP unless I'm missing something blatantly obvious.
(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 error is sometimes The variable LEFT-BANK-MISSIONARIES is unbound.unmatched close parenthesis
or syntax error near unexpected token
('`. With this version of the function the error is the latter.
In Common Lisp there are two forms of local declarations (let
):
(let ((var1 exp1)
(var2 exp2)
...
(varn expn))
exp)
and
(let* ((var1 exp1)
(var2 exp2)
...
(varn expn))
exp)
In the first every expression expi
is evaluated in the environment holding before the let
. In the second every expression expi
is evaluated in the environment containing all the previous declarations var1 ... var(i-1)
.
So in your example the declaration of right-bank-missionaries
uses left-bank-missionaries
which is undefined since it is declared in the same let
.
Simply use let*
to allow the use of every variable immediately after its declaration:
(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))))
Note that the final if
is useless if you want to return a generalized boolean.