Lisp中出错:LET绑定规范格式不正确
我对普通口齿不清真的是个新手,还有些挣扎。我正在研究一个函数,该函数给定x,y和一个数组,如果(x y)中有对角元素,则该数组的垂直值索引返回NIL 但是,当我尝试此函数时,会出现以下错误:Lisp中出错:LET绑定规范格式不正确,lisp,common-lisp,sbcl,clisp,Lisp,Common Lisp,Sbcl,Clisp,我对普通口齿不清真的是个新手,还有些挣扎。我正在研究一个函数,该函数给定x,y和一个数组,如果(x y)中有对角元素,则该数组的垂直值索引返回NIL 但是,当我尝试此函数时,会出现以下错误: ; caught ERROR: ; The LET binding spec (AREF ARRAY LINE) is malformed. ; (SB-INT:NAMED-LAMBDA DIAGONAL? ; (X Y ARRAY) ; (BLOCK DIAGON
; 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))
根据a的要求,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)))
...)
我还注意到,如果您正在生成块,则在同一行上有一个
(
)。这不起作用,因为((如果…)
不是有效的公共Lisp代码。您会得到一个错误,即运算符应该是命名函数或lambda。let
是一个块,因此start(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
需要一个绑定列表。单个绑定是一个变量或(变量值)
:
第三:我们需要一个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
,我们可以测试它
(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)
第五:returnt
不是有效的Lisp表单。我们可以直接返回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
,我们可以在循环
中用另一个替换它
(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)
Eigth:对于从0到n的值
可以替换为以下(+n1)
或最多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
的函数返回,因此我们可以在循环中用直到子句替换它:
(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
。循环的默认返回值现在是T
。只有NEVER
子句失败时,才返回nil
(defun diagonal? (x y array)
(loop for line below 20
for col across array
until (= col -1)
never (= (abs (- x line))
(abs (- y 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)
(defun diagonal? (x y array)
(loop for line below 20
for col across array
until (= col -1)
never (= (abs (- x line))
(abs (- y col)))))