首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >定义闭包函数的setf

定义闭包函数的setf
EN

Stack Overflow用户
提问于 2014-11-09 15:02:15
回答 1查看 255关注 0票数 2

如果我创造了这样的结局,

代码语言:javascript
复制
(let ((A (make-array '(10) :initial-element 5)))    
  (defun h (i)
    (aref a i))
  (defsetf h (i) (x) `(setf (aref ,a ,i) ,x)))

然后,如我所料,(h i)将返回a的第一个元素。

代码语言:javascript
复制
(h 1)  ;; => 5
(h 2)  ;; => 5

但是,尽管setf展开符号正常工作,并正确设置了a的第一个元素,但它也会在SBCL中产生一个警告:

代码语言:javascript
复制
(setf (h 1) 10)

; in: SETF (H 1)
;     (SETF (AREF #(5 10 5 5 5 5 5 5 5 5) 1) #:G1124)
; --> LET* MULTIPLE-VALUE-BIND LET FUNCALL SB-C::%FUNCALL 
; ==>
;   ((SETF AREF) #:NEW0 #(5 10 5 5 5 5 5 5 5 5) 1)
; 
; caught WARNING:
;   Destructive function (SETF AREF) called on constant data.
;   See also:
;     The ANSI Standard, Special Operator QUOTE
;     The ANSI Standard, Section 3.2.2.3
; 
; compilation unit finished
;   caught 1 WARNING condition

在GCL中,会发出错误信号:

代码语言:javascript
复制
>(setf (h 1) 10)

Error: 
Fast links are on: do (si::use-fast-links nil) for debugging
Signalled by LAMBDA-CLOSURE.
Condition in LAMBDA-CLOSURE [or a callee]: INTERNAL-SIMPLE-UNBOUND-VARIABLE: Cell error on A: Unbound variable: 

Broken at LIST.  Type :H for Help.
    1  Return to top level. 

在CLISP和ECL中,示例工作得很好。

在编写了几年的计划之后,我将返回Common,所以我可能在概念上将这两种语言混合在一起。我想我已经触发了根据规范未定义的行为,但我看不出我做错了什么。我很感激你能帮上忙!

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2014-11-09 15:38:44

你的问题

尝试macroexpand通常具有指导意义。

代码语言:javascript
复制
(macroexpand '(setf (h 2) 7))
==>
(LET* ()
  (MULTIPLE-VALUE-BIND (#:G655)
      7
    (SETF (AREF #(5 5 5 5 5 5 5 5 5 5) 2) #:G655)))

如您所见,您的setf调用扩展为一个表单,它在一个文字数组上调用setf,这通常是一个错误的想法,事实上,这正是SBCL警告您的内容:

代码语言:javascript
复制
Destructive function (SETF AREF) called on constant data.

请注意,尽管有警告,SBCL (以及其他一致的实现,如CLISP和ECL)将按您的预期执行。这是因为文字数组是由函数h可以访问的局部变量引用的。

解决方案

我建议你用一个函数代替

代码语言:javascript
复制
(let ((A (make-array '(10) :initial-element 5)))
  (defun h (i)
    (aref a i))
  (defun (setf h) (x i)
    (setf (aref a i) x)))
票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/26829564

复制
相关文章

相似问题

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