再開
ええと、Scm_MakeSubr の理解が微妙。関数名の文脈 (??) 的には手続きオブジェクト作る、って意味か。
ええと微妙なのが Scm_Setter の定義における以下の箇所。
/* fallback to (setter object-apply) */ return Scm_MakeSubr(object_setter, (void*)proc, 0, 1, SCM_OBJ(&object_setter__NAME));
Scm_Setter に渡される ScmObj 型の proc が SCM_PROCEDUREP でない場合なブロック。もしかするとこのあたりは「一般化された set!」の理解が微妙だからかなぁ。もっかいドキュメントをよく読んだ方が良さげ。
ドキュメント読んだ
ええと、一般化された set!] によれば
(set! (foo expr ...) val)
が
((setter foo) expr ... val)
に変換される、との事。Gauche では compile.scm でこの変換を行なっている、のかな?
ココサブさんは以下の式を使用例で挙げている。
(disasm (lambda () ((setter car) list item)))
これは car という手続きオブジェクトが setter 持ってるケイスか。あ、このインストラクションの並びはなんとなく見たコトあるぞ。
;; 0 GREF-PUSH? #<identifier user#list>; list ;; 2 GREF-PUSH? #<identifier user#item>; item ;; 4 GREF #<identifier user#car>; car ;; 6 SETTER ; (setter car) ;; 7 TAIL-CALL?(2) ; ((setter car) list item) ;; 8 RET
どこだったか ... (を
うーん
Scm_MakeSubr の定義が以下。
ScmObj Scm_MakeSubr(ScmSubrProc *func, void *data, int required, int optional, ScmObj info) { ScmSubr *s = SCM_NEW(ScmSubr); SCM_SET_CLASS(s, SCM_CLASS_PROCEDURE); SCM_PROCEDURE_INIT(s, required, optional, SCM_PROC_SUBR, info); s->func = func; s->data = data; return SCM_OBJ(s); }
てーか、段々ワケワカになってきた。Scm_Setter に渡される proc が手続きオブジェクトではない、という事はどーゆー事か、と思いつつ確認。
gosh> (define l '(1 2 3)) l gosh> (setter l) #<subr object-setter> gosh>
これが正に問題となってるソレですな。
gosh> ((setter l) l 'a) *** ERROR: invalid application: (#0=(1 2 3) #0# a) Stack Trace: _______________________________________ gosh>
(setter l) が戻すのは手続きオブジェクトなんじゃないの??といいつつ物凄く脱線している (?) コトに気がついた。あるいは has-setter? が #f を戻す場合にどんな挙動になるのかなぁ、ってこれも脱線ッスか?? (を
もう少し
脱線してみる。
gosh> (has-setter? list) #f gosh> ((setter list) l 'a) *** ERROR: invalid application: (#f (1 2 3) a) Stack Trace: _______________________________________ gosh>
むむ。そのままっちゃそのまんまだ。(何
掘る
object_setter あたり。まず、Scm_GenericObjectSetter って何だろ。掘ってみると class.c にて以下。
SCM_DEFINE_GENERIC(Scm_GenericObjectSetter, Scm_InvalidApply, NULL);
Scm_InvalidApply は class.c にて以下。
/* fallback of object-apply */ ScmObj Scm_InvalidApply(ScmObj *args, int nargs, ScmGeneric *gf) { Scm_Error("invalid application: %S", Scm_ArrayToList(args, nargs)); return SCM_UNDEFINED; }
あらら。てーコトは proc が手続きオブジェクトではない場合はエラーね、って理解で良いのかなぁ。何故に
return Scm_MakeSubr(object_setter, (void*)proc, 0, 1, SCM_OBJ(&object_setter__NAME));
って書き方になってるか、については絶対根拠があるはず。
これ以上脱線すると微妙なので、レビューのコメント書こ。