根据 CLHS 一个 let 具有以下结构:
let
(let (var (var2 expression)) body ...)
这里第一个绑定没有值,但它与写入相同:
(let ((var nil) (var2 expression)) body ...)
您的绑定看起来像这样:
(let (col ; col initialized to nil OK (aref array line)) ; variable aref initialized to? ...)
你的变量 aref 应该只有一个表达式。事实上,你似乎缺乏一套parentesis使它看起来有点像Clojure。也许应该是:
aref
(let ((col (aref array line))) ...)
我也注意到你有一个 ( 在同一条线上,好像你在做一个块。从那以后就行不通了 ((if ....)) 是无效的Common Lisp代码。您会得到运算符应该是命名函数或lambda的错误。 let 是一个块,所以开始 (let ...) 制作一个块,这样你就可以在没有额外括号的情况下拥有多个表达式。
(
((if ....))
(let ...)
首先,非常重要:使用自动缩进。
(defun diagonal? (x y array) (loop for line from 0 to 19 do (let (col (aref array line)) ( (if (= col -1) (return-from diagonal? t)) (let (diag (= (abs (- x line)) (abs (- y col)))) ( if (= diag T) (return-from diagonal? NIL)) ) ))) return T )
然后你的代码用长行看起来很奇怪:永远不要把括号放在他们自己的行上,永远不要用开括号结束一行。
改进:
(defun diagonal? (x y array) (loop for line from 0 to 19 do (let (col (aref array line)) ((if (= col -1) (return-from diagonal? t)) (let (diag (= (abs (- x line)) (abs (- y col)))) (if (= diag T) (return-from diagonal? NIL)))))) return T)
第二: LET 需要一个绑定列表。单个绑定是变量或 (variable value) :
LET
(variable value)
(defun diagonal? (x y array) (loop for line from 0 to 19 do (let ((col (aref array line))) ((if (= col -1) (return-from diagonal? t)) (let ((diag (= (abs (- x line)) (abs (- y col))))) (if (= diag T) (return-from diagonal? NIL)))))) return T)
第三:LET希望有一个Lisp体。这是零个或多个Lisp形式:
(defun diagonal? (x y array) (loop for line from 0 to 19 do (let ((col (aref array line))) (if (= col -1) (return-from diagonal? t)) (let ((diag (= (abs (- x line)) (abs (- y col))))) (if (= diag T) (return-from diagonal? NIL))))) return T)
第四: = 期望数字作为参数。 T 不是一个数字。 = 已经回来了 T 要么 NIL 我们可以测试。
=
T
NIL
(defun diagonal? (x y array) (loop for line from 0 to 19 do (let ((col (aref array line))) (if (= col -1) (return-from diagonal? t)) (if (= (abs (- x line)) (abs (- y col))) (return-from diagonal? NIL)))) return T)
第五: return T 不是一个有效的Lisp表单。我们可以回来 T 直。
return T
(defun diagonal? (x y array) (loop for line from 0 to 19 do (let ((col (aref array line))) (if (= col -1) (return-from diagonal? t)) (if (= (abs (- x line)) (abs (- y col))) (return-from diagonal? NIL)))) T)
第六:我们不需要 LET 对于 col ,我们可以用另一个替换它 FOR 在里面 LOOP 。
col
FOR
LOOP
(defun diagonal? (x y array) (loop for line from 0 to 19 for col = (aref array line) do (if (= col -1) (return-from diagonal? t)) (if (= (abs (- x line)) (abs (- y col))) (return-from diagonal? NIL)))) T)
第七:多重 IF 可以写成一个单一的 COND 。
IF
COND
(defun diagonal? (x y array) (loop for line from 0 to 19 for col = (aref array line) do (cond ((= col -1) (return-from diagonal? t)) ((= (abs (- x line)) (abs (- y col))) (return-from diagonal? nil)))) t)
第八位: for from 0 to n 可以替换为 below (+ n 1) 要么 upto n
for from 0 to n
below (+ n 1)
upto n
(defun diagonal? (x y array) (loop for line below 20 for col = (aref array line) do (cond ((= col -1) (return-from diagonal? t)) ((= (abs (- x line)) (abs (- y col))) (return-from diagonal? nil)))) t)
第九:从那以后 (RETURN-FROM ... T) 从返回的函数返回 T 默认情况下,我们可以用一个替换它 UNTIL 循环中的子句:
(RETURN-FROM ... T)
UNTIL
(defun diagonal? (x y array) (loop for line below 20 for col = (aref array line) until (= col -1) when (= (abs (- x line)) (abs (- y col))) do (return-from diagonal? nil)) t)
第十:因为col只是迭代数组的值:
(defun diagonal? (x y array) (loop for line below 20 for col across array until (= col -1) when (= (abs (- x line)) (abs (- y col))) do (return-from diagonal? nil)) t)
第十一:@Coredump的建议,使用 NEVER 。默认返回值 LOOP 就是现在 T 。那时才回来 nil , 当。。。的时候 never 条款失败。
NEVER
nil
never
(defun diagonal? (x y array) (loop for line below 20 for col across array until (= col -1) never (= (abs (- x line)) (abs (- y col)))))