考虑以下代码:
(defclass test () ((test :initform nil :accessor test)))
#<STANDARD-CLASS TEST>
(defvar *test* (make-instance 'test))
*TEST*这个测试:
(funcall #'test *test*)
nil人们会认为这是可行的:
(setf (funcall #'test *test*) 123)相同于
(setf (test *test*) 123)
123但它的结果是:
; in: LAMBDA NIL
; (FUNCALL #'(SETF FUNCALL) #:NEW1175 #:TMP1177 #:TMP1176)
; ==>
; (SB-C::%FUNCALL #'(SETF FUNCALL) #:NEW1175 #:TMP1177 #:TMP1176)
;
; caught WARNING:
; The function (SETF FUNCALL) is undefined, and its name is reserved by ANSI CL
; so that even if it were defined later, the code doing so would not be portable.
;
; compilation unit finished
; Undefined function:
; (SETF FUNCALL)
; caught 1 WARNING condition为什么它不能工作,我该如何解决它?
我使用SBCL和CLISP对其进行了测试,结果相同。
发布于 2012-05-28 22:39:55
SETF是一种特殊的形式(请参阅http://www.lispworks.com/documentation/HyperSpec/Body/05_aa.htm中解释它的规范部分)。第二个示例之所以有效,是因为lisp实现在语法上解释了(test *test*)。
要了解发生了什么,请查看此会话:
This is SBCL 1.0.56.0.debian, an implementation of ANSI Common Lisp.
More information about SBCL is available at <http://www.sbcl.org/>.
SBCL is free software, provided as is, with absolutely no warranty.
It is mostly in the public domain; some portions are provided under
BSD-style licenses. See the CREDITS and COPYING files in the
distribution for more information.
* (defclass test () ((test :initform nil :accessor test)))
#<STANDARD-CLASS TEST>
* (defvar *test* (make-instance 'test))
*TEST*
* (macroexpand '(setf (test *test*) 123))
(LET* ((#:*TEST*606 *TEST*))
(MULTIPLE-VALUE-BIND (#:NEW605)
123
(FUNCALL #'(SETF TEST) #:NEW605 #:*TEST*606)))
T
* #'(setf test)
#<STANDARD-GENERIC-FUNCTION (SETF TEST) (1)>
* (macroexpand '(setf (funcall #'test *test*) 123))
(LET* ((#:G609 #'TEST) (#:*TEST*608 *TEST*))
(MULTIPLE-VALUE-BIND (#:NEW607)
123
(FUNCALL #'(SETF FUNCALL) #:NEW607 #:G609 #:*TEST*608)))
T请注意,第一个宏扩展获取#'(setf test),它是由defclass调用自动定义的编写器函数。第二个盲目地转换为#'(setf funcall),它不存在(因此出现错误)。
回答你的“我怎样才能解决这个问题呢?”问题,我们可能需要更多地了解您正在尝试做什么。例如,您可以使用像(setf (slot-value object slot-name))这样的东西,它允许您以编程方式选择插槽。
发布于 2012-05-29 03:15:02
:accessor插槽选项定义了两个函数:FOO用于读取槽值,(SETF FOO)用于设置槽值。注意,在Common Lisp中的后一种情况下,函数名不是一个符号,而是一个列表。
如果您想要一个函数和值的列表(您的注释),那么您的列表需要包含setter函数。
(defclass test ()
((foo :initform nil :accessor foo)
(bar :initform nil :accessor bar)))
(map nil
(lambda (function argument)
(funcall function argument object))
(list #'(setf foo) #'(setf bar))
(list arg1 arg2))https://stackoverflow.com/questions/10785839
复制相似问题