lisp - Lisp 中的错误:LET 绑定规范格式错误
问题描述
我对普通的 Lisp 很陌生,并且遇到了一些困难。我正在研究一个给定x,y和具有垂直值索引的数组的函数,如果 (xy) 有任何元素对角线,则返回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))
(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))
解决方案
首先也是极其重要的:使用自动缩进。
(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
不是一个数字。=
已经返回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
。
(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
for 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)
第七:multipleIF
可以写成single 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)
第九:由于(RETURN-FROM ... T)
从一个默认显式返回的函数中返回,我们可以在循环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
now T
。nil
仅当never
子句失败时才返回 then 。
(defun diagonal? (x y array)
(loop for line below 20
for col across array
until (= col -1)
never (= (abs (- x line))
(abs (- y col)))))
推荐阅读
- pandas - 通过基于另一列查找从具有不同形状的 DataFrame 中减去列
- google-bigquery - 将 BigQuery 的聚合具体化转储到 SQL 服务器、Dataflow 与 Airflow
- javascript - 将鼠标悬停在使用 javascript 创建的 div 中
- css - 如何使用动态加载的数据创建备用彩色行?
- c++ - std::chrono::system_clock.now().time_since_epoch().count() 的值是否单调增加?
- azure - Azure 搜索中的动态字段映射
- java - 如何解决“我们发现 'abc.xlsm' 中的某些内容存在问题。您希望我们尽可能多地恢复吗?
- python - 仅使用一个返回作为参数的函数
- pandas - 如何在散景中保持日期时间轴刻度固定?
- python - 不明白当 j 是元组时,这个示例 one-hot 代码如何用 [i,j] 索引 numpy 数组?