Setfの奇妙な拡張


7

setf私は何ができるかを理解しようとして、

(macroexpand '(setf (aref vec i) val))
⇒ (let* ((v vec) (v i)) (aset v v val))

これは明らかに間違っているようです。

しかし、(setf (aref ..失敗する実際のインスタンスを作成できませんでした。例えば

 (setq vec (make-vector 10 nil) i 3 val 'foo)
 ⇒ foo
 (setf (aref vec i) val)
 ⇒ foo
 vec
 ⇒ [nil nil nil foo nil nil nil nil nil nil]

誰かがここで何が起こっているのか説明できますか?


2
OK。今、私は分かる。2つのvシンボルは同じではなく、を(let* ((form (macroexpand '(setf (aref vec i) val))) (symb1 (caar (cadr form))) (symb2 (caar (cdadr form)))) (equal symb1 symb2))返しますnil
PHS

1
不思議なことに、のコードsetfのソースファイルでは、gv.el作成しているようだvのバニラを使用してシンボルを(gensym "v")インターンシンボル作成し、これは「V」接頭辞の後にカウンタ値を追加する必要がありv0v1v2、など
PHSを

2
print-gensym何が起こっているのかをよく理解するために遊んでみてください。
Stefan

@stefan:emacs-26.1があり、print-gensymAFAICT がありません:-( (gensym "v")ソースファイルgv.elが追加されない理由を誰かが説明していますgensym-counterか?!
phs

1
私はあなたが持っていると確信していますprint-gensym、あなたはおそらく間違った場所を見ただけです(のC-h o代わりに試してくださいC-h f)。let*あなたの拡大のコードでは、おそらくによって生成さmacroexp-let2れた用途make-symbolではなくgensym
ステファン

回答:


8

あなたのコメントからあなたはあなた自身でこれを理解しました、しかし...

マクロ展開では、同じ名前の2つの独立したシンボルの印刷表現表示されています。ほとんどの場合、これらのシンボルは両方とも抑留されていません。

このような印刷された表現は、Lispリーダに戻すを渡された場合、あろうない Lispリーダは、インターンのシンボルを同じように、オリジナルと同等です。

これは次のようになります。

(list (make-symbol "v") (make-symbol "v"))
(v v)

3
設定ことは注目に値するprint-gensymprint-circleするにはt何か同等に戻って読むことができます印刷された表現を生成します。
npostavs
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.