美しいプログラミング言語構文を考える

第4回

ブロックを積み上げる

全てはまとまりでありブロックである

囲いとインデント

プログラミングというものは、一般に複数の命令を組み合わせることによって表現される。

しかしながら、ただただ命令を並べていくことだけで複雑な処理を行うのは困難である。

繰り返しや関数、条件分岐などを人間にも理解しやすいように、命令のまとまりを示すためのマーカーが求められていた。

言語やその形状によって細かな名称は異なるが、ここではそれら全般を指してブロックと呼ぶ。

プログラミング言語でこれを実現するために、特に2つのアプローチが取られている。

何かで囲うインデントを揃えるかだ。

囲いによるアプローチはわかりやすいだろう。マーカーとして括弧を用いることが現在では一般的だが、beginendなど特定のキーワードを用いることもある。

ブロック0の要素

{
    ブロック1の要素

    {
        ブロック2の要素
    }
}

インデントを揃えるというのは、同じブロックの要素を同じインデント列に配置するというものだ。

ブロック0の要素
    ブロック1の要素
        ブロック2の要素

この2つにはそれぞれ明確なデメリットがある。

囲いによるアプローチは明らかに複雑に見えてしまう。ブロックの中にブロックがあるような、複数のブロックが重なった入れ子構造のこと。ネストが多くされている場合、ネストが深いなどと言う。 [annotation: ブロックの中にブロックがあるような、複数のブロックが重なった入れ子構造のこと。ネストが多くされている場合、ネストが深いなどと言う。] が深くなるとそれは顕著で、括弧に類するマーカーが少なくない文字数を占有する。

そもそもインデントを用いる方と比較して冗長だ。

インデントを用いるアプローチはユーザ側のインデントによる整形を制限するという問題がある。

改行時に特殊な記号を要求される場合が多い。 [annotation: 改行時に特殊な記号を要求される場合が多い。] に考えなければならないことは増え、スクリプト言語がネットワークを経由する際など、それが求められる場合はある。 [annotation: スクリプト言語がネットワークを経由する際など、それが求められる場合はある。] ために改行をしないという選択も許容しないのである。

このどちらを選択するべきかは、その言語の思想が左右するものである。

だがそもそもの話、ここで例に挙げたブロックというものは狭義のブロックなのである。

すなわち、広義のブロックも当然存在し、そちらにどちらが適すかという話だ。

広義のブロックとは、例えば関数の引数である。

複数の要素のまとまりであり、たいてい括弧に囲われているだろう。

広義のブロックとは、例えば配列の宣言である。

複数の要素のまとまりであり、たいてい括弧に囲われているだろう。

このように複数のものをまとめた存在全てをブロックだと考える。

そうである。広義のブロックを扱う際、囲いによるアプローチを一切採用しないと言うことは稀なのだ。

ここでWyv言語の話へと戻る。

Wyv言語の理想とする美しさには最小限の要素で構成されていることがある。

すなわち、ブロックという概念を表わすものも1つだけで良いのだ。

この時、全てがインデントを用いるアプローチで構成された言語よりも、全てが囲いによるアプローチで構成された言語の方が現実的ではないだろうか。

インデントを用いるアプローチは明らかに見やすさを意識している。

それを採用している言語でさえも、関数の引数など、広義のブロックは囲いによるアプローチで表現していることから、これらを無理に前者に統一することは美しさに繋がらないだろうと言いたいのである。

Wyv言語では囲いによるアプローチを採用するべきだろう。

括弧の弊害と代替案

さて、アプローチだけを決めても仕方がない。何で囲うのかを考える。

一般的に括弧が用いられることは前述の通りだが、ここで言う括弧は1種類だけを指さない。

主に多くのコンピュータにおいて最も一般的な文字コード。アルファベットと最低限の記号および、今では使用されることのない制御文字で構成される。 [annotation: 多くのコンピュータにおいて最も一般的な文字コード。アルファベットと最低限の記号および、今では使用されることのない制御文字で構成される。] 内において、()の組み合わせである丸括弧、{}の波括弧、[]の角括弧に、ASCIIのコレは代替記号だ。大なり小なりとして扱うべきである。 [annotation: ASCIIのコレは代替記号だ。大なり小なりとして扱うべきである。] <>の山括弧がある。

括弧を囲いとして使用する言語の多くでは、これらが複数採用されていることがほとんどだ。

その場合、これらは意味を持つ括弧だ。何で囲うかによって、コードの内容を区別するのである。

ここで考えて欲しいのだが、これらの括弧は文字の形状として非常に細く、かつ似たような見た目をしている。

{(({}))}のようなネストされたブロックを見て、構造を正しく判別することができるだろうか。

「ネストされた2番目の閉じ丸括弧の前に処理を挿入したい」などは日常茶飯事だろう。

もちろんできないことはないのだが、はっきり言って見づらい。

しかもこれは意味を持つ括弧であるので1つでも異なる括弧であった場合、正しくないコードとなる。

前述の例を正しい構造とした場合、{{({})}}は正しくない。

これを書き直せと言われた時、エディタの補助があっても即座に書き直せる自信はない。

インデントでしっかりと整形すれば良いのかと言えば、それならインデントを用いるアプローチにすべきではないか。

インデントの位置に縛られないということは、小さなブロックをまとめて記述できるということだ。

よりによって、小さなブロックのネストをした場合というこのアプローチの利点となるべき際に見づらいのである。これはいけない。

とは言えども、この囲いによるアプローチは表現の幅があり優れているため広く使用されている。

代替となる囲いを見出さなければただの文句でしかない。

次回はブロック第2回、何で囲うべきかを考える。