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

第5回

ブロックを挟み込む

括弧記号に頼らない方法論

縦横無尽のブロック

前回より引き続きブロックの表現方法について考える。

今回は結論を冒頭に出すこととしよう。

Wyv言語で採用するブロック構造は以下のようなものである。

ブロック名 要素 :: ブロック名

要素が空の場合はこうだ。

ブロック名 :: ブロック名

また、ブロック内要素が複数の場合は下記の様になる。

ブロック名 要素0 要素1 要素N :: ブロック名

なお要素が膨大な場合、下記の様にインデントすべきである。

ブロック名
    要素0
    要素1
    要素X
:: ブロック名

Xブロック内でYブロックを構築する様なネストをする場合、要素はブロックである。

X Y :: Y :: X

さらにZブロックをネストする。

X Y Z :: Z :: Y :: X

このブロック構文の最たる特徴はブロック名を明示している点だ。

この手法はHTMLやXMLで用いられる最も有名なHTML要素である<html></html>は、<html>で始まり、なにがしの要素を挟んで</html>で終了する。この始めと終わりの符号をタグと呼ぶ。 [annotation: 最も有名なHTML要素である<html></html>は、<html>で始まり、なにがしの要素を挟んで</html>で終了する。この始めと終わりの符号をタグと呼ぶ。] を利用した構造に近い。

これは括弧と同様に意味を持つブロックだと言える。ブロック名がその意味本体を兼用するわけだ。

なお前回でさんざん考慮した括弧と比較しても明らかに冗長だが、それは可読性とのトレードオフとも言うことができる。

それに付随して本手法で特記すべきことと言えば、終了タグを持つことだろう。

通常の括弧を用いる場合、括弧に加えて情報量を持つ識別子が存在していることが多い。おおむねそれらは開き括弧の前にのみ存在する。

前回悪しき例として挙げた{(({}))}のようなブロックは実際のものと少し異なる。すなわちabc { def(ghi(jkl {})) }のような構造が実際の言語で見られるものだ。

識別子を共なる場合、その言語の規則と括弧の種類によって、前後にスペースが入ることもあるが、これが囲いによるアプローチにおいては、インデントせずに記述することを選択できる都合上、簡潔に記述できるのであれば可能な限り簡潔に記述したい、と言う欲求が発生しやすいと思わないだろうか。括弧そのものの存在が丁度良く小さいから、コードそのものも小さくしたくはならないだろうか。そんな話である。前回の意訳。 [annotation: 囲いによるアプローチにおいては、インデントせずに記述することを選択できる都合上、簡潔に記述できるのであれば可能な限り簡潔に記述したい、と言う欲求が発生しやすいと思わないだろうか。括弧そのものの存在が丁度良く小さいから、コードそのものも小さくしたくはならないだろうか。そんな話である。前回の意訳。] は継続する。

特に見づらさが集中する場所は閉じ括弧周辺であろう。識別子が存在する開き括弧周辺はそこまで言うほどではない。

――――ここで、記述量を犠牲にしてでも閉じ括弧側に識別子を置くなる発想が舞い降りる。

abc { def(ghi(jkl {} jkl)ghi)def } abc

少なくともこれならば、ブロックの位置を把握し逃す問題は解決しそうだ。

それと同時に、上方から読み進めるのと同じように下方からも読み戻すことがブロック内に複数の要素がある場合そうとも言えず、小さな範囲においてのみの話である。近い内に扱う話題になるだろう。 [annotation: ブロック内に複数の要素がある場合そうとも言えず、小さな範囲においてのみの話である。近い内に扱う話題になるだろう。] なのである。

すなわち、これは視点のフックとして利用できる上、構文全体の見づらさを解消することにも通ずるルールだと言えるだろう。

この方向性がそもそもタグを利用した構造そのものであるため、まだ幾つか過程はあるがこれが本手法になると言う経緯でもあった。

非対称性

このブロック構文について真っ先に思うことと言えば、何故ブロック名 :: 要素 :: ブロック名ではないのか、だろう。

開きタグ側の::を消した理由は幾つかあるが、最重要視したことはインデント成形をした際の見栄えだ。

開きタグ側の::はインデント時に位置が安定しないのである。

ABCDE ::
    FGHIJKLMNO ::
        PQRST ::
        :: PQRST

        UVXYZABCDE ::
        :: UVXYZABCDE
    :: FGHIJKLMNO
:: ABCDE

閉じタグ側の::はブロック名の長さに影響されずに、必ず同じ位置に配置されているが、開きタグ側のソレはまちまちである。

すなわち、それが視線の動き的に気に食わないと言う理由だ。

この場合の開き・閉じタグと言うものは視線を向け、ブロックを認識する目安、フックであるべきだと考える。

::はタグを区別するために加えたそれらしい記号なのだが、開きタグを認識することにおいては何の役にも立たないと思ったわけである。

ABCDE
    FGHIJKLMNO
        PQRST
        :: PQRST

        UVXYZABCDE
        :: UVXYZABCDE
    :: FGHIJKLMNO
:: ABCDE

記述量も減少するため、括弧と比較しても良い塩梅の落とし所だろう、と考えたのだった。

制限と拡張

このブロック構文を採用するにあたって、これが言語の文法全体に影響することは避けられないだろう。

ここまでに紹介したブロック構文規則の中にも、その一例がある。

前述の通り、空ブロックを表現する最短の構文はこうなのである。

ブロック名 :: ブロック名

空ブロックを表現するために、ブロック名だけの表記では不正な構文となる。

そもそも構文としてX X :: Xをどのように評価できるだろうか。空のXブロックが2連続している構造と、空のXブロックが別のXブロックに内包されている構造の2パターンが考えられてしまうのだ。 [annotation: X X :: Xをどのように評価できるだろうか。空のXブロックが2連続している構造と、空のXブロックが別のXブロックに内包されている構造の2パターンが考えられてしまうのだ。] のである。

なおこれは開きタグ後の::とトレードオフなのだが、それを抜きに、空ブロックを表現するこれら2つの構文を両立することはできない。

タグに利用する記号が1種類のみであるからだ。ブロックとブロックの切れ目がわからなくなると言うことである。

更に言えば、1つの要素を表現する2つの記法が同時に存在することが良くないと言う思想はこれまでに述べた通りである。

この辺りの調整には底が無いため、ある程度可読性と書きやすさを兼ねる現時点のもので決め打つこととする。

――――そもそもブロック名表記のみの構文に必要性があるか、等とも考えられるかもしれない。

基礎となる概念であるから当たり前なのだが、このブロック構文を考慮せずに今後の構文を考案することは許されない。

Wyv言語はこれに最適化された言語になるだろう。

Wyv言語をこのブロック構文に最適化する場合、最小の単位がブロックである方が効率の面で良いだろう。

最小限の要素で構成されていることを考慮する限り、最大影響を持つ要素をプリミティブな扱いにすべきなのだ。

ありとあらゆる概念はブロック足り得るのだ。

すなわち、可能な限りブロック名 :: ブロック名より小さな構文を発生させないことが理想なのである。

ブロック名表記のみのブロックを許容しないことは、これと同等の結論を招く。

プログラミング言語において、数値や文字列が真っ先に連想される。古典的な列挙体の要素であったり、既存の言語でプリミティブな、すなわち最小限の要素と見なされるものが該当する。 [annotation: 数値や文字列が真っ先に連想される。古典的な列挙体の要素であったり、既存の言語でプリミティブな、すなわち最小限の要素と見なされるものが該当する。] は存在する。

それらを表現する時でさえ、この規則に従わないといけないのはもちろん冗長である。

Wyv言語はこの冗長さと最後まで付き合うことになるのだ。

それを含めて美しさであるのだが、最低限の対応は今後必要となるだろう。

さて、基本のブロック構文が定まったわけだが、これだけでは表現の幅が狭い。

特に2つ以上のブロック間を連結する仕組みが欲しい。

ブロックが2つ以上関わる構文と言うのは多い。

例えば、条件分岐文には条件式と真である場合の処理、偽である場合の処理と3つのブロックが必要だ。

次回はブロック最終回、ブロック拡張についてを扱う。