gpt4 book ai didi

oop - 如何在方法上使用 funcall 来设置对象的属性

转载 作者:行者123 更新时间:2023-12-04 22:28:01 26 4
gpt4 key购买 nike

考虑这段代码:

(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 对其进行了测试,结果相同。

最佳答案

SETF 是一种特殊的形式(参见 http://www.lispworks.com/documentation/HyperSpec/Body/05_aa.htm 规范中解释它的部分)。您的第二个示例有效,因为 lisp 实现在语法上解释了 (test *test*)

要了解发生了什么,请查看此 session :

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)) 的东西,它允许您以编程方式选择插槽。

关于oop - 如何在方法上使用 funcall 来设置对象的属性,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/10785839/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com