我有这个功能:
(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))))
我希望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}>))
结果(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}>)
正如您所看到的,values-list只获取第一个对象,并使我的函数期望两个对象都失败。
答案 0 :(得分:6)
让我们看看values-list
会发生什么:
CL-USER> (values-list '(1 2 3))
1 ;
2
3
此函数获取一个列表并将其项目作为多个值返回。多个值的工作方式是在大多数情况下删除多个值,只使用第一个值(如果没有返回值,则使用NIL
):
CL-USER> (list (values-list '(1 2 3)))
(1)
有多种方法可以使用多个值或使用多个参数调用函数:
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)
但请注意,在您的问题中,您似乎想要使用多个参数调用print:
CL-USER> (print 1 2)
;; error because 2 is not an output stream
如果要打印列表中的每个项目,则可以使用循环或格式:
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
如果你想在中间调用一个具有任意数量参数的函数,那么:
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)
但在你的情况下,我认为实际的解决方案是在第一个参数而不是最后一个参数中传递适用方法的列表。