Andrej Bauer氏はプログラミング言語の設計(リンク)と題したエッセイにて、「プログラマはとても人間らしい。忘れっぽく、不精で、考え得るあらゆる間違いを犯す」という単純な前提に置いた上で次のように語っている。
それゆえプログラミング言語の設計者の仕事は、これらの欠点に立ち向かえるプログラミング言語を作ることなのです。言語は複雑すぎてはならず、プログラマが重要なことを忘れないようにしなければいけません。言語はプログラマの怠惰さをサポートしなければいけません。そのために便利なライブラリをたくさん提供する必要があるし、アイデアを直接的に、簡潔に表現できなければいけません。言語はうまくソースコードを組織化できなければいけません。さもなくば、プログラマはコピペを繰り返すでしょう。言語は積極的にプログラミングの間違いを捕捉しなければいけません。誰もが四六時中起こすようなありふれた間違いは特にです。間違いを見つけたら正確な理由を指摘しなければいけません。なるべくなら人間が理解できるエラーメッセージを添えるべきです。
この原則を適用した最初の節は不明な参照についてだ。氏は次のように語る。
この原則によって不正な参照を許すのが悪いアイデアだというのがわかります。なぜなら、プログラマは必然的にそれを作ってしまうからです。確かに、最近設計された多くの言語、たとえばJavaやPythonなどは次のような明らかに危険なことを書くことは許されていません。
int *p = (int *)0xabcdef;
しかし残念なことに多くの言語設計者が、特別なNULLポインタやnullオブジェクトが同様に悪いアイデアだとは考えていません。
これは特に.NETプログラミングで当てはまる。Javaの「null参照例外」と同様のものを持つだけでなく、Nullable値型でも問題が発生する。Code Contracts(参考記事)に期待できるものの、この技術はまだ製品で利用できる段階ではない。
強い型付けされたオブジェクトとリストベースのデータ構造の対比の後、Andrej氏は定義と変数の対比について議論に移った。氏は.NETプログラミングに当てはまるいくつかの興味深い問題を取り上げている。
もし変数の典型的な使われ方について注意して見てみると、次のようなことがはっきりとわかります。
- 多くの場合変数は一度だけ割り当てられ、(不変な)定義として使われている
- 繰り返しや包含リスト内の変数は、リストやオブジェクトの集合の要素を並べているのに使われている
- ある変数は現在の状態を保持している。これは純粋に可変である
ループカウンタは可変でしょうか?私はそう考えません。繰り返しの本体の中でループカウンタを変えるコードはわかりにくく、エラーになりやすい傾向があります。もしカウンタを使いたければ、代わりにwhileループを使いましょう。3分の2のケースで私たちが欲しい変数が不変であるのに、よく知られるプログラミング言語は変数しか提供していないのです。これはばかげたことです。むしろデフォルトで不変になるように言語を設計すべきです。プログラマが可変量が必要なら、明示的に宣言すべきなのです。
これをC#やVBでできるだろうか?もちろんできる。どちらでも難しくはない。
"assign-once"変数を使うと、型推論を利用できる。C#では"def x = ..."の代わりに"var x = ..."と書く。もしくは単純に既存のキーワードである"Const"を再利用することもできる。これはもちろんVBの哲学にも合っている。つまり、「言ったことを行い、言わないことはしない」という、事前バインディングと遅延バインディングの問題にもあるものだ。重要なのはキーワードが短いことである。もし"readonly"のような長いものを使うのなら、開発者はそれを避けるようになるだろう。
次はさらに簡単だ。ループ変数が変更されるときにコンパイラの警告を出すべきという単純なものだ。
finalオプションは、合法的に可変な変数を使えるがゆえに、珍しいものになってしまっている。もちろん全部が全部ではないだろうが、本当に必要でない限り使わていない。
その他の議題、コンパイル時のチェックとランタイムのチェックについてや未定義の識別子については、主流の.NETプログラマには実際のところ当てはまらない。しかし、もしIronPythonやIronRubyを扱うつもりなら、それらが引き起こすこれらの問題について慣れておくとよいだろう。
概してAndrej Bauer氏の「プログラミング言語の設計」は、次世代のプログラミング言語が取り組むべき類の問題についてのよい手引きになる。