Lisp 中的错误:LET 绑定规范格式错误
Error in Lisp: The LET binding spec is malformed
我对普通的 Lisp 很陌生,遇到了一些困难。我正在研究一个给定 x、y 和 array 以及垂直索引的函数value returns NIL 如果有来自 (x y) 的对角线元素。
(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
)
然而,当我尝试使用此功能时,出现以下错误:
; caught ERROR:
; The LET binding spec (AREF ARRAY LINE) is malformed.
; (SB-INT:NAMED-LAMBDA DIAGONAL?
; (X Y ARRAY)
; (BLOCK DIAGONAL?
; (LOOP FOR LINE FROM 0 TO 19
; DO (LET (COL #)
; (# #)))
; RETURN
; T))
根据 CLHS 一个 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
应该只有一个表达式。事实上,您似乎缺少一组括号,使它看起来有点像 Clojure。也许应该是:
(let ((col (aref array line)))
...)
我还注意到你在同一行上有一个 (
就好像你在制作一个块。这是行不通的,因为 ((if ....))
不是有效的 Common Lisp 代码。您收到错误消息,即运算符应该是命名函数或 lambda。 let
是一个块,所以开头 (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)
:
(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
不是数字。 =
已经 return s 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 形式。我们可以直接 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)
第六:我们不需要col
的LET
,我们可以用LOOP
中的另一个FOR
替换它。
(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
.
(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
(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)
9: 因为 (RETURN-FROM ... T)
returns 来自默认 returns 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
的默认 return 值现在是 T
。 Return 只有 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)))))
我对普通的 Lisp 很陌生,遇到了一些困难。我正在研究一个给定 x、y 和 array 以及垂直索引的函数value returns NIL 如果有来自 (x y) 的对角线元素。
(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
)
然而,当我尝试使用此功能时,出现以下错误:
; caught ERROR:
; The LET binding spec (AREF ARRAY LINE) is malformed.
; (SB-INT:NAMED-LAMBDA DIAGONAL?
; (X Y ARRAY)
; (BLOCK DIAGONAL?
; (LOOP FOR LINE FROM 0 TO 19
; DO (LET (COL #)
; (# #)))
; RETURN
; T))
根据 CLHS 一个 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
应该只有一个表达式。事实上,您似乎缺少一组括号,使它看起来有点像 Clojure。也许应该是:
(let ((col (aref array line)))
...)
我还注意到你在同一行上有一个 (
就好像你在制作一个块。这是行不通的,因为 ((if ....))
不是有效的 Common Lisp 代码。您收到错误消息,即运算符应该是命名函数或 lambda。 let
是一个块,所以开头 (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)
:
(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
不是数字。 =
已经 return s 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 形式。我们可以直接 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)
第六:我们不需要col
的LET
,我们可以用LOOP
中的另一个FOR
替换它。
(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
.
(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
(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)
9: 因为 (RETURN-FROM ... T)
returns 来自默认 returns 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
的默认 return 值现在是 T
。 Return 只有 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)))))