首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >尽管&rest / &body,但常见的Lisp宏参数不匹配

尽管&rest / &body,但常见的Lisp宏参数不匹配
EN

Stack Overflow用户
提问于 2013-04-07 23:37:35
回答 1查看 734关注 0票数 2

我一直在阅读Peter Seibel的书,Practical Common Lisp,按照书中代码的顺序从书中在线拼凑出项目代码,到目前为止,我有一个文件,它依次编译和加载每个章节的代码,这就是我遇到问题的地方:到目前为止,当我加载项目的FASL时,我在ID3v2部分得到了类似下面的警告。

我不明白参数数量冲突是在哪里出现的。UNSIGNED-INTEGER似乎得到了它的两个关键字参数。而且,在我看来,通过使用&rest/&bodyDEFINE-BINARY-TYPE宏将接受任意数量的参数。我想知道你有没有什么建议或建议。下面是一些相关的输出和代码。任何和所有的帮助都是感激的。

提前谢谢你,

代码语言:javascript
复制
; file: .../cl-playlist/id3v2.lisp
; in: DEFINE-BINARY-TYPE U1
;     (BINARY-DATA:DEFINE-BINARY-TYPE ID3V2::U1
;         NIL
;       (ID3V2::UNSIGNED-INTEGER :BYTES 1 :BITS-PER-BYTE 8))
; ...
; ==>
;   (BINARY-DATA:READ-VALUE 'ID3V2::UNSIGNED-INTEGER #:STREAM :BYTES 1
;                           :BITS-PER-BYTE 8)
; 
; caught STYLE-WARNING:
;   The function was called with six arguments, but wants exactly two.

来自"id3v2.lisp“的有问题的函数如下所示,

代码语言:javascript
复制
(define-binary-type u1 () (unsigned-integer :bytes 1 :bits-per-byte 8))

使用

代码语言:javascript
复制
(define-binary-type unsigned-integer (bytes bits-per-byte)
  (:reader (in)
       (loop with value = 0
          for low-bit 
          downfrom (* bits-per-byte (1- bytes)) to 0 by bits-per-byte do
        (setf (ldb (byte bits-per-byte low-bit) value) (read-byte in))
          finally (return value)))
  (:writer (out value)
       (loop for low-bit 
          downfrom (* bits-per-byte (1- bytes)) to 0 by bits-per-byte
          do (write-byte (ldb (byte bits-per-byte low-bit) value) out))))

来自"binary-data.lisp“中的以下内容

代码语言:javascript
复制
(defmacro define-binary-type (name (&rest args) &body spec)
; (defmacro define-binary-type (name &rest args &body spec)
  (with-gensyms (type stream value)
  `(progn
    (defmethod read-value ((,type (eql ',name)) ,stream &key ,@args)
      (declare (ignorable ,@args))
      ,(type-reader-body spec stream))
    (defmethod write-value ((,type (eql ',name)) ,stream ,value &key ,@args)
      (declare (ignorable ,@args))
      ,(type-writer-body spec stream value)))))
EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2013-04-08 00:53:23

你的代码有一个问题,那就是你用错误的参数数量调用函数。已使用较少元素的参数列表创建该函数。

请看以下内容:

代码语言:javascript
复制
CL-USER> (defmethod foo ((a string) (b string) &key) (list a b))
STYLE-WARNING:
   Implicitly creating new generic function COMMON-LISP-USER::FOO.
#<STANDARD-METHOD FOO (STRING STRING) {1005603C53}>

上面说DEFMETHOD还创建了相应的泛型函数,因为没有泛型函数。这很好。我们还可以使用DEFGENERIC来声明泛型函数及其参数。在这里,SBCL从它看到的方法中推断出它。

该方法恰好有两个参数。没有关键字参数。让我们用一些关键字参数从另一个函数调用它。

代码语言:javascript
复制
CL-USER> (defun bar (baz) (foo baz baz :k1 10))
; in: DEFUN BAR
;     (FOO BAZ BAZ :K1 10)
;
; caught STYLE-WARNING:
;   The function was called with four arguments, but wants exactly two.
;
; compilation unit finished
;   caught 1 STYLE-WARNING condition
BAR
CL-USER> 

现在SBCL告诉我们,我们使用四个参数调用泛型函数,即使泛型函数只有两个参数。

在本例中,U1的声明描述了一个带有两个参数的函数。READ-DATA-VALUE没有关键字参数。

现在有几种可能的方法来处理这个问题:

  1. 使用DEFGENERIC来定义带有参数列表的泛型函数READ-DATA-VALUE,并确保所有方法都遵循它。
  2. 将所有参数放在所有方法中。在不使用它们的方法中,将它们声明为其他关键字参数&allow-other-keys,以允许不同的方法具有不同的关键字参数集。最好也在DEFGENERIC表单中这样做。

然后:

代码语言:javascript
复制
CL-USER> (defmethod foo1 ((a string) (b string) &key &allow-other-keys)
           (list a b))
STYLE-WARNING:                                                                                                                                                                                   
   Implicitly creating new generic function COMMON-LISP-USER::FOO1.                                                                                                                              
#<STANDARD-METHOD FOO1 (STRING STRING) {10058AC193}>                                                                                                                                             
CL-USER> (defun bar1 (baz) (foo1 baz baz :k1 10))
BAR1                                                                                                                                                                                             

您可以看到,SBCL不再报错,并假定参数是关键字参数。

缺点是Lisp编译器现在假设您可以对这个泛型函数使用任意的关键字参数,并且不能(也不是在编译时)告诉您是否传递了错误的参数。

票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/15864208

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档