常见的lisp值列表函数

Gak*_*kuo 1 common-lisp

我有这个功能:

(defun call-generic-function (gf &rest args)
    (let* ((applicable-methods (compute-applicable-methods gf  args))
            (most-specific-method (select-next-method-to-call  
                applicable-methods)))
        (print "applicable methods")
        (print (length applicable-methods))  
        (print args)
        (print (values-list args))
        (funcall (method-function most-specific-method)
              (values-list args)         
              (remove most-specific-method applicable-methods))))
Run Code Online (Sandbox Code Playgroud)

我期望values-list给我列表中的所有元素args(这两个对象要通过funcall作为被调用方法的三个预期参数中的两个传递)但它只给出第一个元素并且我得到一个错误,我只是提供2个参数而不是预期的3个参数.这可以通过(print args)打印2个对象的列表但(print (values-list args))仅打印出第一个对象的事实来确认 .我怎么能纠正这个?

结果(打印参数):

(#S(OBJECT
    :CLASS #S(CLASS
              :DIRECT-SUPERCLASS #S(CLASS
                                    :DIRECT-SUPERCLASS #S(CLASS
                                                          :DIRECT-SUPERCLASS NIL
                                                          :DIRECT-SLOTS NIL)
                                    :DIRECT-SLOTS (NAME ADDRESS))
              :DIRECT-SLOTS (EMPLOYER))
    :SLOTS #<HASH-TABLE :TEST EQL :COUNT 3 {1003932403}>)
 #S(OBJECT
    :CLASS #S(CLASS
              :DIRECT-SUPERCLASS #S(CLASS
                                    :DIRECT-SUPERCLASS NIL
                                    :DIRECT-SLOTS NIL)
              :DIRECT-SLOTS (SPORTS))
    :SLOTS #<HASH-TABLE :TEST EQL :COUNT 1 {1003932853}>)) 
Run Code Online (Sandbox Code Playgroud)

结果(print(values-list args))

#S(OBJECT
   :CLASS #S(CLASS
             :DIRECT-SUPERCLASS #S(CLASS
                                   :DIRECT-SUPERCLASS #S(CLASS
                                                         :DIRECT-SUPERCLASS NIL
                                                         :DIRECT-SLOTS NIL)
                                   :DIRECT-SLOTS (NAME ADDRESS))
             :DIRECT-SLOTS (EMPLOYER))
   :SLOTS #<HASH-TABLE :TEST EQL :COUNT 3 {1003932403}>) 
Run Code Online (Sandbox Code Playgroud)

正如您所看到的,values-list只获取第一个对象,并使我的函数期望两个对象都失败.

Dan*_*son 6

让我们看看会发生什么values-list:

CL-USER> (values-list '(1 2 3))
1 ;
2
3
Run Code Online (Sandbox Code Playgroud)

此函数采用列表并将其项目作为多个值返回.多个值的工作方式是在大多数情况下删除多个值,只使用第一个值(如果没有返回值NIL则使用):

CL-USER> (list (values-list '(1 2 3)))
(1)
Run Code Online (Sandbox Code Playgroud)

有多种方法可以使用多个值或使用多个参数调用函数:

CL-USER> (apply #'list 4 '(1 2 3))
(4 1 2 3)
CL-USER> (multiple-value-call #'list (values 4 5) (values-list '(1 2 3)))
(4 5 1 2 3)
Run Code Online (Sandbox Code Playgroud)

但请注意,在您的问题中,您似乎想要使用多个参数调用print:

CL-USER> (print 1 2)
;; error because 2 is not an output stream
Run Code Online (Sandbox Code Playgroud)

如果要打印列表中的每个项目,则可以使用循环或格式:

CL-USER> (loop for item in '(1 2 3) do (print item))
1
2
3
NIL
CL-USER> (format t "~{~a~%~}" '(1 2 3))
1
2
3
NIL
Run Code Online (Sandbox Code Playgroud)

如果要在中间调用具有任意数量参数的函数,则:

CL-USER> (apply #'list 1 (append '(1 2) (list 3)))
(1 1 2 3)
CL-USER> (multiple-value-call #'list 1 (values-list '(1 2)) 3)
(1 1 2 3)
Run Code Online (Sandbox Code Playgroud)

但在你的情况下,我认为实际的解决方案是在第一个参数而不是最后一个参数中传递适用方法的列表.