Lisp中的错误:LET绑定规范格式错误

And*_*iro 2 lisp clisp sbcl common-lisp

我是普通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
)
Run Code Online (Sandbox Code Playgroud)

但是,当我尝试此功能时,我收到以下错误:

; 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))
Run Code Online (Sandbox Code Playgroud)

Rai*_*wig 11

首先,非常重要:使用自动缩进.

(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
  )
Run Code Online (Sandbox Code Playgroud)

然后你的代码用长行看起来很奇怪:永远不要把括号放在他们自己的行上,永远不要用开括号结束一行.

改进:

(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)
Run Code Online (Sandbox Code Playgroud)

第二: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)
Run Code Online (Sandbox Code Playgroud)

第三: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)
Run Code Online (Sandbox Code Playgroud)

第四:=期望数字作为参数.T不是一个数字.=已经退货TNIL我们可以测试.

(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)
Run Code Online (Sandbox Code Playgroud)

第五: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)
Run Code Online (Sandbox Code Playgroud)

第六:我们不需要LETcol,我们可以用另一个替换它FORLOOP.

(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)
Run Code Online (Sandbox Code Playgroud)

第七:多个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)
Run Code Online (Sandbox Code Playgroud)

Eigth: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)
Run Code Online (Sandbox Code Playgroud)

第九:自从默认(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)
Run Code Online (Sandbox Code Playgroud)

第十:因为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)
Run Code Online (Sandbox Code Playgroud)

第十一:@Coredump的建议,使用NEVER.的默认返回值LOOP是现在T.nilnever子句失败时才返回.

(defun diagonal? (x y array)
  (loop for line below 20
        for col across array
        until (= col -1)
        never (= (abs (- x line))
                 (abs (- y col)))))
Run Code Online (Sandbox Code Playgroud)

  • 第十一?使用"从不"而不是"退货"? (3认同)

Syl*_*ter 6

根据CLHS, a let具有以下结构:

(let (var  (var2 expression))
  body ...)
Run Code Online (Sandbox Code Playgroud)

这里第一个绑定没有值,但它与写入相同:

(let ((var nil) (var2 expression))
  body ...)
Run Code Online (Sandbox Code Playgroud)

您的绑定看起来像这样:

(let (col                  ; col initialized to nil OK
     (aref array line))    ; variable aref initialized to?
 ...)
Run Code Online (Sandbox Code Playgroud)

您的变量aref应该只有一个表达式.事实上,你似乎缺乏一套parentesis使它看起来有点像Clojure.也许应该是:

(let ((col (aref array line)))
  ...)
Run Code Online (Sandbox Code Playgroud)

另外我注意到你有一个(在同一条线上,好像你在做一个块.这((if ....))是行不通的,因为它不是有效的Common Lisp代码.您会得到运算符应该是命名函数或lambda的错误.let是一个块,所以开始(let ...)创建一个块,这样你就可以在没有额外括号的情况下拥有多个表达式.