Common Lisp:无法在Paul Graham';这是一本书

Common Lisp:无法在Paul Graham';这是一本书,lisp,common-lisp,Lisp,Common Lisp,我是Lisp新手 我正在读保罗·格雷厄姆的书《ANSI通用Lisp》 第38页有一个解压缩功能。它需要一个对列表,其中对中的第一项是一个数字,表示第二项中应该有多少项。例如,解压缩此文件: ((3 a) (2 b) c) 应产生以下结果: (A A A B B C) 我在Lisp解释器(GCL-2.6.2-ANSI)中键入了uncompress函数,然后像这样测试它: (uncompress '((3 A) B (2 C) (5 D))) (defun uncompress (lst)

我是Lisp新手

我正在读保罗·格雷厄姆的书《ANSI通用Lisp》

第38页有一个
解压缩功能。它需要一个对列表,其中对中的第一项是一个数字,表示第二项中应该有多少项。例如,解压缩此文件:

((3 a) (2 b) c)
应产生以下结果:

(A A A B B C)
我在Lisp解释器(GCL-2.6.2-ANSI)中键入了
uncompress
函数,然后像这样测试它:

(uncompress '((3 A) B (2 C) (5 D)))
(defun uncompress (lst)
  (if (null lst)
      nil
    (let (elt (car lst))
      (rest (uncompress (cdr lst))))
    (if (consp elt)
        (append (apply #'list-of elt)
                rest)
      (cons elt rest))))
产生此错误消息的:

Error in IF [or a callee]: Too many arguments.

Fast links are on: do (use-fast-links nil) for debugging
Broken at IF.  Type :H for Help.
 1 (Abort) Return to top level.
下面是
解压缩功能。我想我是忠实地把书上写的东西打出来的。我已经测试了每件作品,每件作品似乎都能正常工作。说实话,我被困住了。我不知道是什么导致了这个错误。谢谢你的帮助

(defun uncompress (lst)
   (if (null lst)
       nil
       (let (elt (car lst))
            (rest (uncompress (cdr lst))))
        (if (consp elt)
            (append (apply #'list-of elt)
                    rest)
            (cons elt rest))))

(defun list-of (n elt)
   (if (zerop n)
       nil
       (cons elt (list-of (- n 1) elt))))

您有最典型的常见lisp语法错误:括号使用不正确

以下是正确的版本:

(defun uncompress (lst)
  (if (null lst)
      nil
      (let ((elt (car lst))
            (rest (uncompress (cdr lst))))
        (if (consp elt)
            (append (apply #'list-of elt)
                    rest)
            (cons elt rest)))))

由于这些类型的错误在没有使用专门编辑器的情况下非常常见,我建议您使用诸如Emacs或Vim之类的编辑器来编辑您的程序。

您有最典型的常见lisp语法错误:括号使用错误

以下是正确的版本:

(defun uncompress (lst)
  (if (null lst)
      nil
      (let ((elt (car lst))
            (rest (uncompress (cdr lst))))
        (if (consp elt)
            (append (apply #'list-of elt)
                    rest)
            (cons elt rest)))))

由于这些类型的错误在没有使用专门编辑器时非常常见,因此我建议您使用诸如Emacs或Vim之类的编辑器来编辑程序。

如果您使用编辑器缩进工具,代码如下所示:

(uncompress '((3 A) B (2 C) (5 D)))
(defun uncompress (lst)
  (if (null lst)
      nil
    (let (elt (car lst))
      (rest (uncompress (cdr lst))))
    (if (consp elt)
        (append (apply #'list-of elt)
                rest)
      (cons elt rest))))
这样会更容易发现这个错误。从语法上讲,它是错误的,因为IF
的形式不超过三种

(defun uncompress (lst)
  (if (null lst)   ; the IF has four subforms, one too many
      nil
    (let (elt (car lst))  ;<- variables ELT and CAR? Makes no sense
      (rest (uncompress (cdr lst))))   ; <- not using the result?
    (if (consp elt)    ; <- fourth form in IF? Does not make sense.
        (append (apply #'list-of elt)
                rest)
      (cons elt rest))))
在Common Lisp中,可以在
LET
的主体形式顶部添加声明:

let ({var | (var [init-form])}*) declaration* form* => result*
Common Lisp中IF
语法为:

if test-form then-form [else-form] => result*
缩进

通常,手动缩进Lisp代码不是一个好主意。让编辑器或IDE来做。确保所有代码都正确缩进

如果您有语法问题:首先重新缩进表达式->这确保代码正确缩进,然后更容易查找问题。接下来编译代码并读取编译器错误消息。CommonLisp有很好的编译器,有些有很好的错误报告

代码

代码也不是很好:它在存在高阶函数或循环更好的地方使用递归

这个版本同时得到了两个:高阶
MAPCAN
循环:

(defun uncompress (list)
  (mapcan #'expand-item list))

(defun expand-item (item)
  (typecase item
    (atom (list item))
    (cons (destructuring-bind (n element) item
              (loop repeat n collect element)))))

如果使用编辑器缩进工具,代码如下所示:

(uncompress '((3 A) B (2 C) (5 D)))
(defun uncompress (lst)
  (if (null lst)
      nil
    (let (elt (car lst))
      (rest (uncompress (cdr lst))))
    (if (consp elt)
        (append (apply #'list-of elt)
                rest)
      (cons elt rest))))
这样会更容易发现这个错误。从语法上讲,它是错误的,因为IF
的形式不超过三种

(defun uncompress (lst)
  (if (null lst)   ; the IF has four subforms, one too many
      nil
    (let (elt (car lst))  ;<- variables ELT and CAR? Makes no sense
      (rest (uncompress (cdr lst))))   ; <- not using the result?
    (if (consp elt)    ; <- fourth form in IF? Does not make sense.
        (append (apply #'list-of elt)
                rest)
      (cons elt rest))))
在Common Lisp中,可以在
LET
的主体形式顶部添加声明:

let ({var | (var [init-form])}*) declaration* form* => result*
Common Lisp中IF
语法为:

if test-form then-form [else-form] => result*
缩进

通常,手动缩进Lisp代码不是一个好主意。让编辑器或IDE来做。确保所有代码都正确缩进

如果您有语法问题:首先重新缩进表达式->这确保代码正确缩进,然后更容易查找问题。接下来编译代码并读取编译器错误消息。CommonLisp有很好的编译器,有些有很好的错误报告

代码

代码也不是很好:它在存在高阶函数或循环更好的地方使用递归

这个版本同时得到了两个:高阶
MAPCAN
循环:

(defun uncompress (list)
  (mapcan #'expand-item list))

(defun expand-item (item)
  (typecase item
    (atom (list item))
    (cons (destructuring-bind (n element) item
              (loop repeat n collect element)))))

不,在
let
中,变量绑定周围的参数太少。这不是Clojure.:-)啊!!我看到了失踪的左帕伦。非常感谢。它现在工作得很好。顺便说一句,我真的很喜欢Lisp;这是一种非常漂亮的语言。不,在
let
中,变量绑定的参数太少了。这不是Clojure.:-)啊!!我看到了失踪的左帕伦。非常感谢。它现在工作得很好。顺便说一句,我真的很喜欢Lisp;多么漂亮的语言啊。@RogerCostello也可以从中看到。@coredump:MAPCAN在这里很好,因为列表是新使用的,可以很好地链接起来。;-)@RogerCostello也可以从这里看到。@coredump:MAPCAN很好,因为列表是新使用的,可以很好地链接起来。;-)