Ruby のブロック渡しの構文は、自分にとって衝撃的だった。
元々は、別の言語にあった物らしいが、便利で美しく、すばらしい構文だ。
ただ、ブロックを1つしか渡せないので、関数として if ~ else if ~ else 文や
switch 文、 try ~ catch ~ finally 文などが作れないのが惜しい。
そこで、自分が作ろうとしている新しいプログラミング言語の為に、
複数ブロック渡しの構文を考えてみた。
複数ブロック渡しの構文は、大きく分けて2種類ある。
1つは、節(section)によるブロック内分割であり、
もう1つは、ブロック連結子による連結である。
■節(section)によるブロック内分割
これは、Rubyのような単一のブロック渡しのブロックの内部を、
COBOLのような節(section)によって分割するというもの。
次のような構文となる。
foo(paramA){ …… // sectionA(paramB) // …… // sectionBoo // …… }
ここで、「// …… //」を名前つきの節の開始とし、
次の節の開始か、ブロックの終端を、その節の終端とする。
この構文では、ブロック全体を1つのレキシカルスコープとするか、
少なくとも先頭の名前の無い節を共通のレキシカルスコープとする。
それによって、 Java の try { … } catch ( … ) { … } finally { … } で
try ブロックで定義した変数に finaly ブロックからアクセスできない
という不便を解消できる。
■ブロック連結子による連結
関数呼び出しとブロックの間と、ブロックと関数呼び出しの間に
ブロック連結子を導入する。
ここでは、「~」をブロック連結子とする。
次のような構文となる。
foo(zzz)~{ …… }~bar(xxx)~{ …… }~piyo~{ …… }
これは、C言語の if ( … ) { … } else if ( … ) { … } else { … } と同じように
一つのブロック({ … })毎に異なるレキシカルスコープを持つ。
ブロック連結子には、幾つかのやり方があるだろう。
一つは、独立した演算子のように扱う方式がある。
これは、前述のようなものばかりではなく、
foo(zzz)~bar(xxx)~{}~piyo~piyo
のように間にブロックが無い記述も許容することができる。
もう一つは、「~」と「{」、あるいは、「}」と「~」を一つの記号として扱う方式がある。
これによって、必ず、ブロックを間に挟まなくてはならなくなる。
他には Ruby のような単一ブロック渡しを特別に扱う方式がある。
つまり、関数呼び出しとその後ろのブロックの間に
ブロック連結子を必要としない。
foo(zzz){ …… }~bar(xxx){ …… }~piyo{ …… }
のような形となる。
■導入の方針
節(section)によるブロック内分割とブロック連結子による連結は、
意味が異なるため、両方とも導入したい。
節(section)によるブロック内分割は、 try ~ catch 文や siwtch 、
ブロックを抜ける際に必ず実行する部分を表す finally 節などとして使うだろう。
ブロック連結子による連結は、 if文や for 文、 do ~ while 文等のために使われることになる。
ただ、ブロック連結子による連結の幾つかの方式の内、どれを採用するかは検討中である。
構文だけなら、どのようにでも複数ブロック渡しの構文を考えることができるだろう。
しかし、問題は、実際にどのような意味を与えて、どのような形でデータとして保持して、
どのように処理するようにするかであろう。
それは、これからの課題である。