マクロの問題とは? わかりやすく解説

マクロの問題

出典: フリー百科事典『ウィキペディア(Wikipedia)』 (2020/10/02 16:40 UTC 版)

健全なマクロ」の記事における「マクロの問題」の解説

健全なマクロ機能持たないプログラミング言語では、マクロの展開中に作成され変数束縛によって、すでに存在する変数束縛隠されてしまう可能性がある。C言語では、次のようなコードによってこの問題説明できる。 #define INCI(i) {int a=0; ++i;}int main(void){ int a = 0, b = 0; INCI(a); INCI(b); printf("a is now %d, b is now %d\n", a, b); return 0;} C言語プリプロセッサ上のコード変換すると、次のコード生成されるint main(void){ int a = 0, b = 0; {int a=0; ++a;}; {int a=0; ++b;}; printf("a is now %d, b is now %d\n", a, b); return 0;} トップスコープ宣言され変数 a は、マクロ中にある変数 a によって隠されしまっている。その結果プログラム実行して変数の値は変化せずコンパイルされたプログラム次のように出力するa is now 0, b is now 1 この問題解決する最も簡単な方法は、現在のプログラム含まれるどんな変数とも衝突しない名前を、マクロ変数与えることである。 #define INCI(i) {int INCIa=0; ++i;}int main(void){ int a = 0, b = 0; INCI(a); INCI(b); printf("a is now %d, b is now %d\n", a, b); return 0;} INCIa という名前の変数作られないかぎり、この解決方法によって正し出力得られるa is now 1, b is now 1 現在のプログラムでは問題解決されたが、この解決策は十分頑強であるとはいえない。プログラマは、マクロ内部使用され変数と、残りプログラム使われる変数とを、常に衝突しないように気をつけなければならない。たとえば、変数 INCIa についてマクロ INCI使おうとすれば以前マクロで変数 a について問題起きたのと同じよう問題が起こることになる。 「健全な問題」は、変数束縛拡張加える。次のようなCommon Lispマクロ考えてみる。 (defmacro my-unless (condition &body body) `(if (not ,condition) (progn ,@body))) このマクロには、変数への参照含まれていないので、シンボル"if"、"not"、"progn" は、すべて普通の定義に束縛される。しかし、上のマクロ次のように使用され場合、 (flet ((not (x) x)) (my-unless t (format t "This should not be printed!"))) "not"の定義はローカルな定義に置き換えられ、my-unless の展開結果が変化する。(標準関数オペレータグローバルまたはローカルな再定義は、ANSI Common Lispによれば不確定な振る舞い起こすとされている。そのため、上のような使い方をしても、実際に実装によってエラー判断される可能性がある。) 一方健全なマクロは、すべての識別子("if"や"not")のレキシカルスコープ自動的に保存される。この性質は、「参照透過性」と呼ばれている。 しかし、プログラム内で定義した関数同じようには保護されていないので、次のようなコードでは問題が起こることがある。 (defmacro my-unless (condition &body body) `(if (user-defined-operator ,condition) (progn ,@body))) (flet ((user-defined-operator (x) x)) (my-unless t (format t "This should not be printed!"))) この問題Common Lispでの解決策は、パッケージ利用することである。 パッケージ中に置かれた my-unless マクロでは、user-defined-operator はそのパッケージ内のプライベートなシンボルである。そして、ユーザーコード内の user-defined-operator は異なシンボルとなり、マクロ内のシンボルとは無関係なものになる。 しかし、健全なマクロ使用しているSchemeなどの言語は、マクロ展開の処理の一部として自動的に参照透過性保証することで、識別子の誤捕捉防いでいる。ただし、識別子意図的に補足するために、健全なマクロメカニズム明示的に無視できるようにしている実装もある。 たとえば、次のSchemeによるmy-unless の実装は、期待通り振る舞いをする。 (define-syntax my-unless (syntax-rules () [(_ condition body) (if (not condition) body (void))])) (let ([not (lambda (x) x)]) (my-unless #t (displayln "This should not be printed!")))

※この「マクロの問題」の解説は、「健全なマクロ」の解説の一部です。
「マクロの問題」を含む「健全なマクロ」の記事については、「健全なマクロ」の概要を参照ください。

ウィキペディア小見出し辞書の「マクロの問題」の項目はプログラムで機械的に意味や本文を生成しているため、不適切な項目が含まれていることもあります。ご了承くださいませ。 お問い合わせ



英和和英テキスト翻訳>> Weblio翻訳
英語⇒日本語日本語⇒英語
  

辞書ショートカット

すべての辞書の索引

「マクロの問題」の関連用語

マクロの問題のお隣キーワード
検索ランキング

   

英語⇒日本語
日本語⇒英語
   



マクロの問題のページの著作権
Weblio 辞書 情報提供元は 参加元一覧 にて確認できます。

   
ウィキペディアウィキペディア
Text is available under GNU Free Documentation License (GFDL).
Weblio辞書に掲載されている「ウィキペディア小見出し辞書」の記事は、Wikipediaの健全なマクロ (改訂履歴)の記事を複製、再配布したものにあたり、GNU Free Documentation Licenseというライセンスの下で提供されています。

©2025 GRAS Group, Inc.RSS