糖衣構文

出典: フリー百科事典『ウィキペディア(Wikipedia)』
移動先: 案内検索

糖衣構文(とういこうぶん、: syntactic sugar)は、プログラミング言語において、読み書きのしやすさのために導入される書き方であり、複雑でわかりにくい書き方と全く同じ意味になるものを、よりシンプルでわかりやすい書き方で書くことができるもののことである。構文上の書換えとして定義できるものであるとも言える[1]

syntactic sugarの直訳に近い構文糖(こうぶんとう)とも言い、糖衣構文あるいは構文糖衣とするのは少々意訳的だがよく言われている。

解説[編集]

糖衣構文はプログラムの意味としては同じものを、よりわかりやすい構文で書けるものである。ジャーゴンファイルのsyntactic sugarの項[2]では、アラン・パリスの「構文糖はセミコロンのガンをひきおこす」という言を引用[3]している(ジャーゴンファイルのこの記述は、そのひとつ前の項目である「構文塩」(syntactic salt)の項[4]にある「構文塩は不健康にプログラマの血圧を上げる」という(こちらは引用ではない)記述と対応していて、colon cancer(結腸癌)とセミコロンを掛けてもいる[5])。

逆に糖衣構文から元の構文に戻すことをdesugarとか脱糖という。糖衣構文の役割を考えると無駄な作業に思えるが、実際にどうなっているかを把握するためであるとか、場合によっては短く書けたり、また一般に柔軟性(自由度)は元の書き方のほうがすぐれる。脱糖したコードを把握しておくことが重要な一例として、Haskellモナドが挙げられる。Haskellには、(モナドをなしている対象を)命令型言語のコードに似せたスタイルで書ける、do式(do expressions[6])という糖衣構文があり、例えばmainのIOモナドを書く際などは全く「モナドらしい扱い」といったものは考えなくてよい。しかし、自分でその対象自身を書く場合は、do式を脱糖したコードに現れる演算子(具体的には >>= という演算子[7])を、その対象について定義しなければならないからである。

糖衣構文の例[編集]

C言語[編集]

ポインタへの配列風アクセス[編集]

C言語では、例えばオフセット付きでポインタをデリファレンスするような式 *(p + ofs) を、配列へのアクセス風に p[ofs] とも書ける。この糖衣構文は、見た目の単純さだけではなく、括弧の手前に書かれるものが先頭アドレスで括弧の中がオフセットであるというように、コードの意味をより明確で分かりやすくもしている。

一方で、配列とポインタは違う(例えば extern int *a; という宣言と extern int a[]; という宣言とは、それぞれ違うものである)という事実を見失わせ、関数への実引数などでは配列がその先頭要素へのポインタになるという事実との混同から、あらゆる場所で配列とポインタは混同できると混同するようなCプログラマを増やす要因にもなっている。 

なお、前述の p[ofs]ofs[p] のように書くこともできる。例えば文字列リテラルにインデックスでアクセスする、整数値から一六進表現を得るための、次のようなコード "0123456789abcdef"[n] の代わりに n["0123456789abcdef"] と書くこともできる(普通は書かないが)。構文的に問題なく、意味的にも全く同じだが、読者を驚かせる効果はある。IOCCCにおいて以前はよく見られた技法のひとつである。

ポインタを介したメンバ選択演算子[編集]

C言語では、構造体へのポインタと矢印演算子によりメンバを参照できる。

p->member

ここで、p構造体へのポインタ、member は構造体の要素名である。 ポインタをデリファレンスする * 演算子と、構造体の値に対しメンバを選択する. 演算子を組み合わせて、次のように等価な式を書くことができる(が、倍の文字数と、カッコを必要とし、意味を持つ部分が * と . の2箇所に分散してしまっている)。

(*p).member

なおC++では、演算子のオーバーロードにより、これらが等価ではない場合もありうる(基本的には等価になるようにオーバーロードされるべきではあるが)。

Erlang[編集]

Erlang でのレコード型データは、実際にはタプル型データに対する糖衣構文であるが、要素を取り出したり、パターンマッチするのに糖衣構文が使われる。

%% レコードの定義(コンパイラー・マクロ)
-record(book, {title, author, lang, isbn}).

%% タプル {book, "Learn You Some Erlang for Greate Good!", "Fred Herbert", en, "978-1-59327-435-1"} になる。
B = #book{title="Learn You Some Erlang for Great Good!", author="Fred Herbert", lang=en, isbn="978-1-59327-435-1"}.

%% タプルの要素取り出し element(2, B). の糖衣構文
B#book.author.

%% タプルの要素置き換え setelement(2, B, "F. Herbert"). の糖衣構文
B#book{author="F. Herbert"}.

%% レコードのパターンマッチの部分はタプルのパターンマッチ printCover({Title, Author, _, _}) の糖衣構文
printCover(#book{title=Title, author=Author})
  -> io:format("~p by ~s~n", [Title, Author]).

Java[編集]

Javaの配列の宣言と初期化の記法

String[] strs = new String[3];
strs[0] = "a";
strs[1] = "b";
strs[2] = "c";

String[] strs = { "a", "b", "c" };

と書ける[8]String以外のオブジェクトでも可能である。 後者は「あらかじめ決まったいくつかの文字列から文字列の配列を作りたい」という記述者の思考を、より良く反映している。


ML[編集]

ここでは、ML系の言語のDerived Formsについて説明する。[9]

t_1 ; t_2 は、手続き型言語においても見受けられるように、いわゆる命令文の列であるが、型付きラムダ計算において、 (λx:Unit : t_2) t_1 と表すことができる。(ここで、Unit はユニット型 である。)

Perl[編集]

Perlの条件文の記法

if ($boolean) {
  print "Syntax sugar\n";
}

print "Syntax sugar\n" if $boolean;

と書ける。

Perlの開発者ラリー・ウォールによればこれは糖衣構文であるが、プログラマの中にはこれを読みにくいと感じる者も多い。それは、「読み書きのしやすさ」が主観に基づくためである。

注・参考文献[編集]

  1. ^ これを「マクロで定義できるもの」とするのはあまり正確ではない。C言語をはじめ、多くの言語のマクロはテキストレベルであり、構文木を自在に編集することは困難であるためである。Lispであれば「糖衣構文はマクロで定義できる」と言える。
  2. ^ http://catb.org/jargon/html/S/syntactic-sugar.html
  3. ^ 1982年にSIGPLANに掲載された en:Epigrams on Programming からの引用である。
  4. ^ http://catb.org/jargon/html/S/syntactic-salt.html
  5. ^ 基本的には語呂合わせのダジャレだが、合成甘味料に関してしばしばその発ガン性が話題になることに掛けている。
  6. ^ https://www.haskell.org/onlinereport/haskell2010/haskellch3.html#x8-470003.14
  7. ^ http://hackage.haskell.org/packages/archive/base/latest/doc/html/Prelude.html#v:-62--62--61-
  8. ^ Java Language Specification Third Edition, 10.6
  9. ^ Types and Programming Languages ,"Pierce, Benjamin C.","ISBN : 0-262-16209-1"