SBCL 中的生物医学信息学原理:这个 let 有什么问题?

Principles of Biomedical Informatics in SBCL: what's wrong with this let?

这里是 Lisp 新手,倾向于相信我肯定误解了一些东西,因为这是第二版相当长的书的第 35 页的问题。我一直在阅读 let 绑定,所以让我通过引用他来确保作者的*意图是明确的:

In the following code, the symbol pos serves as a temporary storage or variable that has as its value the result of the position function expression. Finally, how will we accumulate the results? The recursive call should give us a list of the remaining positions, so the first one found should just be put on the front. We already have a function to do this, the cons function

这是代码:

(defun all-pos (item seq start)
  (let ((pos (position item seq :start start))
    (if pos
        (cons pos
          (all-pos item seq (+ 1 pos)))
    nil))))

这是错误:

Ch1_Notes.lisp:27:5:
  error: 
    The LET binding spec (IF POS
                             (CONS POS (ALL-POS ITEM SEQ (+ 1 POS)))
                             NIL) is malformed.

Compilation failed.

这是不言而喻的错误吗?我还应该包括一些前面的代码吗?

*作者 Ira J. Kalet 已经去世,所以我不能问他。

您似乎遇到了不平衡的括号问题。一种查看方式是查看 NIL 之后的右括号。这将关闭 IF 语句。在那之后还有两个关闭的,它们将关闭 LET 和 DEFUN。但是,在那之后你还有一个。这就是导致问题的原因。

如果出现此类错误,重新缩进代码通常很有用。通常可以在编辑器中使用键盘命令来完成。

但 Lisp 还带有内置代码格式,称为 漂亮打印:

CL-USER > (let ((*print-right-margin* 60))
 (pprint '

; your code follows:

(defun all-pos (item seq start)
  (let ((pos (position item seq :start start))
    (if pos
        (cons pos
          (all-pos item seq (+ 1 pos)))
    nil))))

))

输出如下所示:

(DEFUN ALL-POS (ITEM SEQ START)
  (LET ((POS (POSITION ITEM SEQ :START START))
        (IF POS (CONS POS (ALL-POS ITEM SEQ (+ 1 POS)))
         NIL))))

这样可以更容易地看出 ifpos 变量绑定处于同一缩进级别。 这不可能!

要使用 Lisp 格式化您的代码,您只需要:

(let ((*print-right-margin* 60))
  (pprint '

; here goes your code

))

Lisp 会为您格式化...

正如我之前的回答者所提到的,一个简单的括号问题:

;; correct version:

(defun all-pos (item seq start)
  (let ((pos (position item seq :start start)))
     (if pos
         (cons pos
               (all-pos item seq (+ 1 pos)))
  nil)))

;; e.g.
(all-pos '3 '(1 2 3 4 3 5 4) 0)
;; returns (2 4) - correctly