先日書いた日記の訂正記事です。
いつものことなのだけど、調査して面白い事実を見つけたら、とりあえず書いちゃってます。
で、公表すると各所から突っ込みが来るので、再調査してみると思っていたのと違った、ということもしばしば。
ちゃんと調査してから書け、と言われそうだけど、1人で考えていると気づかない部分とかあって、書いた時点では正しいと思っているんですよ。
この方針については以前表明した通り。
さて、今回一番の訂正事項は、「BCPL が世界で最初に { } を使った言語である」という点。
Wikipedia をはじめとして、多くのページにもそう書いてあります。
先回りして書けば、これは間違いではありません。
昔のキーボードって { } は使えませんでした。
BCPL はなぜ、一般的でなかった { } を使ったのだろう、と「最初に { } が搭載された機械探し」を始めた人がいました。
そして、僕も調査に参加したわけです。
その調査報告が前回の日記なのですが、大きな間違いがありました。
誰も疑問に思わなかった前提…「BCPL は世界で最初に { } を使った言語である」というのが間違っていた。
いや、先にも書きましたが、間違いではない。でも、間違っている。
すごく事情が込み入っていて、この短い文章では正確な表現になっていないのです。
前回、TX-2 に移植された BCPL マニュアルを提示して、時期・地理的にオリジナルも同じだろう…と判断していました。
実は、この時点でオリジナルのマニュアルを探していたのだけど、見つけられてませんでした。探し方が悪かった。
TX-2 マニュアルも隅々までは読めておらず、若干勘違いがあった。
その後、BCPLの最初のマニュアル(1967)を発見しました。
予想外なことに、一切 { } を使っていませんでした。
最初に { } を使った、と言われている言語は、一切 { } を使っていなかった。
このマニュアル、当時の紙資料を基に、OCR して再度 PDF 化したものです。
その意味では「作り直された」もので、資料性は落ちますが、検索性が上がっていて便利。
わざわざ手間をかけて配布しているのは、C言語作者のデニス・リッチーです。
実は、恨み節を述べるために手間をかけてまで配布している節がある。
ところで、デニスが持っているのとは別のバージョンを、ドイツのクライネさんも公開しています。
こちらはスキャンしたそのままです。
デニスもクライネも、完全なバージョンを持っていたわけではなく、一部ページが欠落しています。
しかし、この2つを合わせることで、ほぼ完全な内容がわかります。
デニスによれば、興味深いことにこの2つの資料は、別のタイプライターで印刷されたものだそうです。
書いてある内容はほぼ同じなのに、文字サイズが違うためにページ割が違う、とのこと。
当時は紙テープにタイプ内容を記録し、同じ内容を何度でも印字することができました。
紙テープに互換性のある別のタイプで印刷が行われたのでしょう。
オリジナル BCPL マニュアルの PDF の配布ページでは、デニスの思い出話も書いてあります。
冷静で落ち着いた語り口になっていますが、実は BCPL 作者のマーティン・リチャーズに対して恨み節を述べています。
デニスは、ブロックを示す文法について、こう言います。
「リチャーズが例示したプログラムでは、$( $) になっている。
現在、リチャーズはBやCで使われるような { } を使って例を示すことがある。」
リチャーズのWEBページには、現代のパソコン用に移植された BCPL や、そのサンプルプログラムがあります。
これらは、すべてブロックを作るのに { } を使っています。
デニスは、これを「Cの影響を受け、後から改竄したのだ」と断じています。
言葉にはしていませんが、Cが有名になったので、「 { } を最初に使った言語」という手柄を横取りしようとしているのだ、と言っているように思います。
ところで、BCPL は CPL (1963) から派生したものです。
僕は残念ながら、CPL という言語を知りません。名前は知っているけど、使ったことはない。
ネット上の情報によれば、ALGOL 60 をベースとして、COBOL などの「事務処理言語」として必要な機能を持たせようとした結果、非常に巨大になってしまって実用性を失ってしまった言語、のようです。
CPL の作者は、ケンブリッジ大学のクリストファー・ストレイチー。
世界初の「マクロ言語」を開発した人でもあります。
この「マクロ言語」は、コンパイラの前段階として、テキストを置換する簡単な処理をするもの。
実は、以前に MUSYS の話で、このマクロ言語のことを書いています。
マクロ言語は、コンパイラに、簡単な置換を行うフィルタを組み合わせるだけで、ずっとプログラムが幅広いものになる、と示すものでした。
CPL は、Titan と呼ばれるコンピューターで実装されました。
Titan は、Atlas という名前で市販されたコンピューターのプロトタイプ機(1962)。
なので、CPL は Atlas でも動いたそうです。
リンク先の写真に、テレタイプ端末が写っています。
Atlas では Friden 社の Flexowriter が使用されたらしいので、これも Flexowriter ではないかと思うのですが、型番特定には至っていません。
この端末では、§(セクション)記号が使えたそうです。
Wikipedia の英語版の BCPL のページの「ノート」で、ケンブリッジ大学の卒業生だという方が、1975年にはまだこのタイプライターが使われており、§ が使えた、と証言しています。
#2016.2.26 追記
これ、少し違うようです。別記事にまとめました。
§は「表記できたけど、入力できたわけではない」。
使えたという証言も、表記できたことを言っているか、直接タイプ出来たように記憶違いしているのでしょう。
そして、CPL の文法では、この記号でブロックを示します。
ブロックとは、つまりセクションです。この記号で示すのは、わかりやすいように思います。
ちなみに、セクションの終了は、記号の上に縦棒を重ね打ちして、「打消し」つまり終了を表現します。
(タイプライタなので、1文字戻って別の文字を重ね打ちすることができました)
BCPL は、この CPL を簡略化して、現実的に実装できるようにしたもの。
リチャーズがケンブリッジ大学で言語仕様を定め(1966)、その後 MIT を訪問した際に実装(1967)したもの、だそうです。
ケンブリッジ大学で CPL を簡略化しようとしていたのだから、おそらくはストレイチーの示唆があったのかと思います。
BCPL では、言語の処理を3段階に分け、移植性に考慮しています。
一番中心となる「BCPLコンパイラ」は、BCPL で記述され、どのコンピューターにも簡単に移植できました。
コンパイラが生成するのは、中間コードでした。
この中間コードを実際のコンピューターの命令に変換するには、コンバーターが必要となります。
ここは移植ではなく、機種ごとに作らないといけない部分。
でも、コンパイラを作るよりは簡単でした。
そして、コンパイル前に簡単な文字列置換を行う、「プリプロセッサ」と名付けられた処理が存在していました。
ちょうど、CPL を作ったストレイチーの「マクロ言語」のように、コンパイル前に文字列置換を行うのです。
ただし、BCPL のプリプロセッサは、固定された動きしかしなかったようで、マクロ言語としては使用できません。
じゃぁ、何をするのかと言えば、機種ごとに異なる「記号」を変換し、言語本来の表現に変換するためのものでした。
これにより、BCPL コンパイラは、一切の記号・英小文字を必要としませんでした。
f(a+b) という記述があれば、プリプロセッサにより F RBRA A PLUS B RKET と変換され、そのあとでコンパイルされます。
これは、当時のどんなテレタイプでも扱えることを意味します。
BCPL の最初の実装は、MIT の CTSS …改造された IBM 7094 でした。
前回、リンカーン Flexowriter が接続されたのではないか…と推測していたのですが、これは全く大外れで、IBM 1050 が接続されている、と BCPL マニュアルに明記されていました。
IBM 1050 では § も、 { } も使えませんでした。
そこで、$( $) でブロックを示します。
§に似た形の $ を使い、始まりと終わりを示すために ( ) を付け加えた…ということのようです。
風説では、BCPL では { } を使い、この記号が使えない環境では $( $) で代替した、となっています。
まぁ、代替したのはあっているのですが、{ } の代替ではなく、§の代替だった、というのが真相でした。
先に書いたように、BCPL は、記号を英大文字の単語に変換します。
括弧には3種類があります。
( ) [ ] $( $) は、それぞれ RBRA RKET SBRA SKET SECBRA SECKET となります。
頭についた R S SEC は、おそらく Round Square SECtion の意味でしょう。
BRA と KET は、括弧を意味する英単語 bracket の初めと終わりの3文字です。
SECBRA と SECKET は、Titan では1文字で表現できたのに、CTSS では括弧が2種類しか使えなかったため、2文字での表現になっています。
実際の記号と予約語の対応は、機種によって全く異なります。
Alto 用の BCPL のマニュアル(1979)を見たとことでは、SECBRA SECKET nに相当する部分は、[ ] になっていました。
じゃぁ、SBRA と SKET はどうなったのか…
これらは、連続したメモリアクセス…つまりは配列を作るためのものでしたが、配列には ! でアクセスするようになっています。
Alto で作られた有名なプログラム言語…Smalltalk では、ブロックの表現に [ ] を使います。
また、Smalltalk を中間言語にコンパイルすると、メモリアクセスは ! で表現されるそうです。
Alto ユーザーにとってわかりやすいように、記号類を再定義したのでしょうか。
#この部分、間違えていました。再訂正です。(2016.2.15)
Xerox 内では、Smalltalk より先に BCPL が普及していました。
詳細は再訂正記事書きました。
また、PDP-11用のOSである tenex 用の BCPL マニュアル(1974)もありました。
こちらでは、SECBRA と SECKET は { } になっています。TX-2 と同じです。
いずれにせよ、ブロック定義は § $( $) { } [ ] など、いろいろな表現があったことがわかります。
ここら辺、プリプロセッサという仕組みが柔軟だからできることでもあります。
ところで、Alto 版や tenex 版のマニュアルには、BCPL 作者のマーティン・リチャーズの名前は入っていません。
TX-2 版マニュアルには、リチャーズの名前が入っています。
どうやら、移植はほかの人がやったのではなく、本人の作業のようです。
CTSS 版は 1967 年。TX-2 版マニュアルは 1969年になっていますが、冒頭に「改訂版が完成した」という手紙がついています。
TX-2 移植がいつかはわからないのですが、1969年よりも早い時点で…おそらくは、リチャーズが滞在している 1967年ごろに移植が行われていたのでしょう。
というのも、このマニュアルの表紙のリチャーズの名前の下には、連絡先としてケンブリッジ滞在中の住所が書かれているのです。
Alto 版マニュアルには、TX-2 版を元に作成された NOVA 版を移植したものである、という注釈がついています。
Data General 社の NOVA 用の BCPL もまた、リチャーズが直接移植したものです(1978)。
#この部分も間違えていました。再訂正です。(2016.2.15)
NOVA 版 BCPL には2つあり、上に書いたリチャーズの公式移植以前に、Xerox 内で勝手移植されていました。
詳細は再訂正記事書きました。
tenex 版のほうにも、TX-2 版を元にしているという説明があります。
NOVA 版 BCPL についても、マニュアルなどを探したのですが見つかりませんでした。
ただ、ここで TX-2 版を元にしている、ということから、リチャーズは CTSS 版よりも TX-2 版のほうを気に入っていた、という事かと思います。
§ を使うのが本来の姿だけど、ないなら $( $) よりも { } のほうが良かった、ということなのでしょう。
話を戻します。
C言語の作者、デニス・リッチーは、{ } だけでなく、論理和や論理積の表現についても異議を申し立てています。
リチャーズは ∧ ∨ などの論理記号や、場合によっては & で書きたがるが、当時は記号を使わず LOGAND LOGOR などと書いていた、記号でこれらを示すのはB言語(1969年ごろ)の発明である、というのです。
しかし、TX-2 版では ∧ ∨ を使っています。
tenex 版では & \ で、Alto 版では & % です。
C言語が一般に知られるのは、UNIX の配布が始まった 1974年ごろから。1978年の「プログラム言語C」の出版で急激に広まります。
tenex 版は 1974年ですから、& を使っているのはCの影響というより、「AND」の記号として & を使うという、ごく自然な選択かと思います。
Alto 版は 1979年なので影響があってもおかしくないけど、むしろ tenex と同じ発想ではないかな。or の表現は両方とも違うし。
たしかにBよりも後ではありますが、そもそもBはCが有名になってから知られるようになったものです。
これらをBの真似だ、とするのは違うでしょう。
ここからは推測です。
BCPL の CTSS 版(1967)を元にして、すぐに Multics 版と TX-2 版が作られたのではないでしょうか。
移植性を気にして作られているのですから、すぐに移植してみるというのはありそうです。
デニスとケンは、移植のために CTSS 版 BCPL のマニュアルを渡された。
それをデニスは保存していて、公開した。
移植は仕様通り… CTSS 版をほぼそのまま移植する形で行われた。
Multics 版のマニュアルなどは見つからなかったのですが、Multics の BCPL で書かれたソースの一部は見つかりました。
日付は 1973 年となっているので、ずいぶんと後のものです。しかし、CTSS 版と同じく、$( $) を使っていることがわかります。
一方で、リチャーズは TX-2 への移植に立ち会い、あまりに文字セットが異なる TX-2 のリンカーン Flexotype 用に、各種記号の意味を割り振った。
実際、TX-2 版はオリジナルと比べると、多くの記号を使うように変更されています。
そして、この記号セットを気に入り、以降の BCPL は TX-2 版をベースにするようになった。
…非 ASCII 文字はどうしようもなかったでしょうけど、ASCII に取り入れられた { } などは、そのまま使えます。
∧などは、先に書いたように & に変更するなどの違いがあったと思います。
ただ、少しおかしなところもあります。
リチャーズは、1969年にBCPLの論文を発表しています。
ここでは、プログラム部分が手書きになっており、ブロックの表記に $( $) を使っています。
一応、本文の中で「非常に文字セットが限られた機械でも使える」と説明しているので、{ } などの一般的でない文字を使わなかっただけ、というようにも思いますが。
TX-2 は Project MAC で使用されてはいますが、Project MAC 自体はコンピューターの研究をなんでも行うごった煮プロジェクトで、Multics 開発で TX-2 を使った、というわけではありません。
そして、デニスとケンは、Multics 開発のために Project MAC に参加したのです。TX-2 版の BCPL を知らなかったとしても当然でしょう。
AT&T が Multics から撤退(1969)した後、ケンは UNIX を作り上げます。
そして、その上で BCPL を簡略化した、B言語を作ります。
このときに、ブロック表記は { } となりました。
別に、TX-2 版を知らなくても、当然のように同じ記号に行きついたのではないかと思います。
先に書きましたが、BCPL の文法上、3種類の「括弧」が必要でした。
CPL が考案された Titan のテレタイプ端末では、3種類が使えました。
しかし、通常のテレタイプ端末では、2種類しかありませんでした。
だからこそ、3つ目に $( $) という2文字の組み合わせを使っていたのです。
ここに、 { } という「3番目の括弧」が登場したなら、当然それを使うでしょう。
TX-2 のリンカーン Flexowriter では、3種類目の括弧として { } が使えました。
ASCII 対応した端末でも、3種類目の括弧として { } が使えました。
両方とも3種類目が { } だった、というのは偶然で、しかし3種類目の括弧があるならそれをブロックに使う、というのは必然です。
ビット演算に & を使った、というのも、先に書いた BCPL の各種移植と同じように、必然的なものでしょう。
さて、長くなったので要点だけをまとめ直しましょう。
・BCPL は、記号部分を自由に変えられる実装。
当初仕様ではブロックを § で、CTSS 版では $( $) で示したが、TX-2 版では { } で示す。
・リチャーズは TX-2 版が気に入ったようで、以降は TX-2 版をベースとし、各機種に移植し続ける。
tenex 版のように、直接移植したわけではないバージョンでも、TX-2 由来のものがベースとなった。
・ケンは CTSS 版 BCPL を元にB言語を作った。この際、ASCII が使えるようになったので、ブロックを { } で示すように改良。
ブロック表現に関しては、おそらく TX-2 の影響はない。
・デニスはB言語を元にC言語を作った。このC言語は有名になり、現在でも標準的な言語の地位にある。
・BCPL が「最初に { } を使った言語」と呼ばれるようになり、事実と異なるとデニスが反発。
以上を前提として、蛇足っぽくなりますが前回から引き続いての結論を。
世界で最初に { } を使えるキーボードを搭載したコンピューターはどれだろう、という最初の問いかけへの答えは、TX-2 です。
より厳密には、TX-2 に接続された、リンカーン Flexowriter 端末のキーボードが { } を使えるようになっていました。
前回、この Flexowriter を CTSS にも接続したのではないか…と考えていたのですが、これに関しては誤りでした。
お詫びいたします。
リンカーン Flexowriter は TX-2 (と、今回の話に関係ない TX-0)でしか使えなかったようです。
問いかけの裏にあった、なぜ { } が一般的でなかった時代に、BCPL で { } を使おうと思ったのか…という疑問自体は、「疑問の前提が間違えている」が答えになります。
BCPL では、当初 { } を使おうとは考えていません。
$( $) 表記は { } が使えないときの代用表記…と一般的に考えられていたのですが、この考え方が誤りで、$( $) は § の代用表記でした。
TX-2 に移植する際に、この代用表記が { } に変わります。
また、$( $) 表記をしていた BCPL からB言語が作られた際に、TX-2 版とは無関係に { } が使用されるようになります。
BCPL は { } を使った最初の言語なのか?
これに関しては、立場の違いでどちらともいえます。
「最初」というのは、「由来」を聞いているのでしょうか?
それとも「一番最初に登場した」言語を聞いているのでしょうか?
同じテーマの日記(最近の一覧)
関連ページ
デニス・リッチーの誕生日(1941)【日記 13/09/09】
再訂正:BCPL と Smalltalk の関係【日記 16/02/15】
再訂正:BCPL と Smalltalk の関係【日記 16/02/15】
別年同日の日記
申し訳ありませんが、現在意見投稿をできない状態にしています。 |