Upgrade to Pro — share decks privately, control downloads, hide ads and more …

まだ間に合う!今年の夏こそSchemeのマクロ展開器を完全理解!

 まだ間に合う!今年の夏こそSchemeのマクロ展開器を完全理解!

Kernel/VM探検隊@東京 No. 19での発表スライド。

Avatar for Masanori Ogino

Masanori Ogino

August 22, 2026

More Decks by Masanori Ogino

Other Decks in Programming

Transcript

  1. Scheme とマクロシステム • プログラミング言語の「マクロ」システムの表現力はさまざま ‣ C: 文字列置換プリプロセス、一部 C コンパイラと連携 ‣(古典的)Lisp:

    コードとデータが同型 ‣ Haskell: 抽象構文木操作とコード生成(Template Haskell) ‣ Rust: 宣言的マクロ macro_rules!と手続き的マクロ proc_macro • Scheme は広義の Lisp だが、(古典的)Lisp と異なる解法を採用 ‣ 高レベルマクロ: 専用のパターン言語で記述(Rust でいう宣言的マクロ) ‣ 低レベルマクロ: Scheme 自身で記述(Rust でいう手続き的マクロ) • Scheme のマクロは衛生的(hygienic)と形容される ‣ 変数捕捉の禁止(または意図しない変数捕捉の防止) ‣ 参照透過性 1/6
  2. 変数捕捉 • (or a b) を素朴に if で書き換えると (if a

    a b) ‣ だが、a の観測可能な副作用が 2 回起きうる ‣ (let ((tmp a)) (if tmp tmp b)) に置き換えると a を 1 度だけ評価する • ここで ((lambda (tmp) (or #f tmp)) 7) について考える ‣ この式を 1 ステップ簡約すると(or #f 7)となり、最終的な結果は 7 のはず ‣ 素朴にマクロ展開すると ((lambda (tmp) (let ((tmp #f)) (if tmp tmp tmp))) 7)、結果は #f ‣ or の定義で tmp が使われていたために、 tmp を含む式が特殊な扱いを受ける • これを変数捕捉の問題と呼ぶ • 衛生的マクロは定義に含まれる tmp と展開先に含まれる tmp を区別する 2/6
  3. 参照透過性 • (or a b) が (let ((tmp a)) (if

    tmp tmp b)) に展開されるとする • ここで (let ((if 7)) (or #f if)) を簡約すると…… ‣ 期待通り (if #f #f 7) という式になるだろうか? ‣ それとも (7 #f #f 7) という式になるだろうか? ‣ あるいは (if #f #f if) という式になるだろうか? ‣ ひょっとして (7 #f #f if) という式になるだろうか? • マクロの定義時と展開時の文脈が混同されるとこのような問題がある • これをマクロの参照透過性の問題と呼ぶ • 衛生的マクロは定義時の if と展開時の if を区別する 3/6
  4. 二原子識別子モデル • Michael D. Adams. 2015. Towards the Essence of

    Hygiene. In Proceedings of the 42nd Annual ACM SIGPLAN-SIGACT Symposium on Principles of Programming Languages (POPL ‘15). Association for Computing Machinery, New York, NY, USA, 457–469. https://doi.org/10.1145/2676726.2677013 ‣ 衛生的なマクロシステムが満たすべき基準を提案 ‣ 基準を満たすモデルの例として識別子を 2 つのアトムの組としてコンパイラ内部 で管理する二原子識別子(biatomic identifier)モデルを提唱した • 二原子識別子は syntax-rules 高レベルマクロを実現するのに十分な表現力を持つ ‣ 対話的なトップレベル(REPL)はそのままではうまく表現できない (本文でトップレベルの扱いはスコープ外と明記) ‣ syntax-case などの低レベルマクロを実現するには不足 4/6
  5. おわりに • Scheme マクロの衛生性とは識別子の扱いに関する性質 • 変数捕捉と参照透過性の問題は変数スコープと生存区間に関する問題のマクロ版 • Scheme はこれらの問題を静的な構文規則と整合する形で解決した ‣

    レキシカルスコープ ‣ クロージャ ‣ 衛生的マクロ • 二原子識別子は衛生的マクロの唯一のモデルではない ‣ マーク・置換 ‣ スコープ集合 • syntax-case 以外の低レベルマクロシステム ‣ 明示的改名(explicit renaming) ‣ 暗黙的改名(implicit renaming) ‣ 構文閉包(syntactic closure) • Scheme の知見は後発言語のマクロシステムとも繋がっている 6/6