[View] [Edit] [Attachments] [History] [Home] [Changes] [Search] [Help]

言語ゲーム落書き

言語ゲームに関する(または関係ない)アイデア落書きです。

SQL

いまさら言うのも何だが、SQLはダサい!
リレーショナルデータベースの概念自体は、大変きれいで使いやすく、業務にもフィットする物なのだが、それを操作するSQL言語は、何で今どきこんな物が使われているのだろうと思うほどダサい。世の中には自分で言語を作るひとが沢山いるのに、ちょっと調べてもSQLに代わる物を開発している人は居なかった。何でかな?

SQLの良いところ

もしSQLに代わる物を作るとしたら、SQLの良いところを受け継がなくてはいけない。

SQLのいやなところ


責任分割がしにくいと言うのは、OO言語だと例えば alpha beta というオブジェクトがあった場合に、オブジェクトごとに操作をまとめて隠蔽できる。だけどSQLだと、複数のテーブルはいわばグローバル変数のような扱いになっていて、表をカプセル化する事が出来ない。

アイデア

SQL言語自体はDBとのインタフェースとして広く使われているので、移植性のために無くす事は出来ない。そこで、OO的にクエリを表すオブジェクトを作成して、それをSQL文に変換する仕組みを作ったらよいのではないかと思う。 -- 2003-04-26

形式仕様について


僕は仕様書を書くのがめちゃくちゃ苦手だ。
なぜかといろいろ考えてみたのだが、やはり最大の理由は検証不可能な事。コードを書いてしまえばあってるかどうかすぐわかるにのに、VISIOの段階では間違っていてもエラーを出してくれない。だからみんなに見せる前に頭の中でシミュレートして矛盾がないかどうか調べるのだが、こんなに不毛な作業は無い。しかもVISIOで書いた図はダサい。

「形式仕様」という単語を聞いた時に、もしかするとこれらの悩みを一挙解決してくれるものでは無いかと思った。使用を明文化することが可能で、しかも検証可能なのであれば、業務の能率は相当上がるはずだ。しかし google で検索しても出てくるのは難しい論文ばかりで、僕らが使えるようになるまでにはまだまだ相当先のようだ。仕方が無いので、自分が仕様作成支援の為のツールを作るとすればどんな物が必要か考えてみる。

大きく見るとツリー構造

これは単なるXMLでも良いのだが、やっぱり大まかには一貫してツリー上の構造をしていた方が分かりやすい。VISIO やパワーポイントなどは、画面単位で操作するようになっていて、これはこれでシンプルなのですが、もうちょっと大きな単位で、しかも任意の粒度で書類を分割できるようにしてほしい。

ひとつのオブジェクトは同じ物を指す

いろんな画面でいろんなオブジェクトを違う形式で表現するけど、これらはすべて内部的にはつながっていて欲しい。ある属性の名前を変えると全部変わって欲し。
また、関連も同じ物は全部つながって欲しい。

自由にデザインを変えたい

最初からついてくるデザインは大抵ダサい。クラス図の字の太さや大きさやフォントなど、自分で格好良く変えたい。しかもひとつ変えると全部変わって欲しい。

と、ここまではもしかするとすでにあるソフトで実現可能だと思う。これ全部静的構造だから。だけど仕様書の中のに、こういう場合。。。と書かなくてはいけない時、ものすごく図はややこしくなる。これはどうやったら解決するのか分からない。場合分けほどうっとうしいものは無い。こういう時にもしかしたら形式仕様が
役に立つのでは無いかもしれないと思うので勉強しないと。

仕様記述言語

花子は夢見がちな10歳の女の子だ。都会に住む彼女は空想の中でいつも
美しく青い海に囲まれた小さな島での生活に憧れていた。だから大人たちが
アリスに彼女の理想の暮らしを尋ねると、驚く程正確に夢のプラン、
家の輪郭はどんなであるとか、庭にはどんな木が植えられているか、
海までの距離や昼と夜の温度差、理想の夏の長さ等を描写する事が出来た。
だから彼女は、道具を与えられた時に、寸分違わずそれを作り上げたのだ。

太郎はやんちゃな10歳の男の子だ。彼の好奇心は旺盛で、目に触れる物を
すべて分解して壊してしまうかと思えば、両親に隠れて裏の森で秘密の小屋を
作り、遠くの町に冒険に出かけ一人で帰って来れなくなったりした。
彼に何を聞いても返ってくるのは出鱈目なジョークばかりだったが、
物や人を見る目は鋭く行動力は旺盛で、しばしば人を驚かせた。
彼に道具を与えても計画性はなく力任せで、周りは何の期待もしていな
かったが、直感を駆使して何故かそのすばらしいものが出来上がってしまった。

プログラミングはおそらくこのような二つの側面を持つ。--2003-03-24

超テスト

言語ゲームの成果(?)の中で、特に実用性がありそうな概念が「超テスト」だ。テストファーストという言葉はご存知だろうか?プログラムの品質を上げるために、あるルーチンを書く前にあらかじめそのルーチンが満たすべき条件をテストプログラムとして記述するというものだ。テストファーストはなかなか意思が弱いと難しいものだが、満たすべき条件=仕様をプログラムとして記述すると言う点は非常に有効だ。

テストファーストはXPの重要な概念だが、言語ゲームのインクリメンタルコンパイル機能と、Smalltalk 自身が持つ依存の機能を使えば、コードを一文字打つたびに関連するテストを実行してしまうと言う事も出来る。これが「超テスト」。これで何が嬉しいだろうか?例えばエディタの上にプログラスバーがあって、キーを打っていってテストが通る度にバーが伸びて行くなんて事が出来る。ゲーム感覚のコーディングだ。

実際はデータベース周りのルーチンを書いている時など、不意に妙な字を入力した途端に開発環境がぶっ潰れてしまうという事にもなりかねないので、「テスト」という概念自体について深く考察する必要がある。超テストは副作用の無いテストにしか使えない。

テストって何だろう。考えてみるとこれは非常に興味深い概念だ。論理的に物事を記述するには二通りの方法があって、それは演繹と帰納だ。もしも仕様書がこの二つをだけを使って注意深く書かれていたら、プログラマは悩まず仕事をする事が出来るだろう。だけど問題なのは、帰納も演繹も直感的では無いということだ。つまり、普通仕様をお客さんと話すときにいきなりルールに基づいた仕様が出てくるわけじゃなくて、「こういう場合はこうなってて、こういう場合は確かこうで」と話していくうちに僕らがルールを見出していくという作業になる。つまり最初の要求はプログラムよりもテストに近い。

もしも人工知能が実現すれば、要求から仕様が生成できるようになるかも知れないが、ご存知のとおり意外とその道は遠いらしい。ならば要求を要求のまま開発に生かすにはテストが一番だ。注意点としては、テストでは間違っていることは示せても合っている事は示せない事がある事だ。

で、この前提のもとに「超テスト」環境での開発は例えばこんな感じ。
ビジネスルールを元に大まかな親テストを書く。親テストは失敗する。
もうちょっと実装よりの子テストを書く。子テストが通るなら親テストが通ることを試す。(さらっと書いてしまったけど、これって大変かも)子テストは失敗する。
子テストが通るようなコードを書いてゆく。コードを書くにつれて自動的に依存する子テストが実行される。子テストが成功すると依存する親テストが成功する。
親テストが成功する事は、仕様を満たしていると言う事である。-- 2003-02-10

プレゼンを終えて

最終レポートのアイデアスケッチです。
まず高い評価を頂いたノードにパーサの参照を持たせ、ノード自身に文を解釈させるという発想について。これはオブジェクト思想そのままなので、Smalltalk 上に実装すると大変きれいなのですが、これがLL文法で上手く行っても、LR、もしくはバックトラックの含まれるLLで上手くいくとは限らない(というか失敗した)。この場合のノードとは非終端記号の事だが、先読みをしないとルールを決められないと言うことになると、その状態を保留しなくてはいけなくなってしまう。えっと、だから何だったっけな?とにかく、ややこしいので止めたのでした。LRを使いたい理由は簡単で、2項演算子の解析が左結合になると言う理由だけなんだけど。

あとプレゼンでも論文でも触れなかったけど、言語ゲームが関数型言語を志向している。つまり状態も時間もなく定義だけが存在する世界を扱っていると言う点で、せっかくきれいなオブジェクトの世界を持っている Smalltalk に関数型の概念を持ち出して来ても良いものなのか(しかも素人向けに!)という気はする。ここは、T-Gen のようにあるクラス間の構造をビルドするだけの黒子に徹すると言うやり方が正しいのかも知れない。

拡張BNFについて、アランケイは拡張BNF(正規表現風のBNF)を使ったら表記が簡単になるとアドバイスしてくれたが、ここは悩むところで、わざと再帰定義だけにしておいてもそれはそれで慣れたら使えるものなので、むしろ再帰のスマートさを優先させたほうが良いと教育的配慮を見せるのは技術者のエゴだろうか??

次にデバッガ。タイルスクリプティング程度の世界であればデバッガは不要なのかも知れないけど、メタプログラミングを体験すると言う点、あとプログラムカウンタの存在を意識させると言う点で、デバッガはやはり必要だと思う。今回モールと言う例外を使用した簡易デバッガを用意したが、ここは元もとの Smalltalk の環境を利用して、言語ゲームとは独立して作動する汎用モールを作ったほうが面白いかも知れない。

総括として、「GUIつきのパーサジェネレータを作る」といういたってシンプルな命題から始まったプロジェクトだが、その風呂敷が大きくなりすぎて戸惑っている。その風呂敷の中身を簡単に列挙すると
(1)タイルスクリプティングに再帰の概念を導入。
(2)タイルスクリプティングに関数的概念を導入。
(3)パーサを持ち、途中から解析可能なパーサにより、コード入力時のコード補完、依存と組み合わせて完全リアルタイム単体テストフレームワーク、入力制限フレームワークなど。
(4)タイルスクリプティングにデバッグの概念を導入。
(5)イメージつきタイル。絵文字によって別の国の人のプログラムでも理解できる。 -- 2003-02-02

依存地獄

ああ、もうプレゼンまであとこんだけしかないのか、キビシー!
プログラムの方は依存のスパゲッティになってしまって、目も当てられない
パフォーマンス。これでなんとかプレゼンをやり過ごすしかないが、きちんと
設計しないとこんなことになっちゃう。ソースをみて依存の使い方のコツを
覚えようとしたけど、けっこうみんな書き方ちがうし。。。
あー墜ちてゆく! -- 2003-01-27

LR 失敗か?

昨日一日かけてLRをタイルスクリプティングに使う実験をしていたが、僕の実力ではどうも無理みたいです。LRというものがそもそも単語を先に読んでそこから非終端記号に還元していく物なので、ツリーの途中だけ解釈するというのが難しいからです。つまり先読みがネックで、先読みの結果結局ツリー全体をパースしなおさないといけなくなる可能性があると言うことです。もうちょっと順を追って考えたらうまくいくのかも知れないけど、締め切りも近いし、何とかLLでやってみよう。

こういう仕事をして思うのが、頭の働く速さと言葉の選び方には相関性があると言うことです。この終端記号やら非終端記号という単語はどう考えてもダメダメとしか言いようが無い。そこで新しく単語を考えることにしました。
つまり、非終端記号というものは、終端記号を与えられて初めて意味が現れるということが言いたいわけ。卵も豆も、記号と意味にまつわる神秘的な意味合いがあって良いと思うのだが如何でしょうか? -- 2002-12-30

LLか? LRか? それが問題だ

タイルスクリプティングを汎用的なパーサに解析させようとした場合、ぱっと考えではLL解析器が適している。タイルによるプログラミングとは、プログラムがこれから作られる可能性をあらわすスタートシンボルから枝葉を作っていく作業で、感覚的に下向き(LL)解析と同じだからだ。予測的構文解析になるように文法を変形してしまえば、ドラッグされたシンボルに対してルールが一意に定まり、それに基づいて新たなシンボルを出すなり何なりしてやればよい。

しかし文法の変形には問題があって、たとえば E = E + E | <number> 1 + 4 + 2 等という文に対して左再帰性の問題を解決すると 1 +(4 + 2) となり、直感と異なってしまう。教育ツールとして考えた場合、あいまい性などの問題は出来たら避けて通りたいわけで、理論的には正しくないがなぜかちゃんと動いてしまうものが理想(?)であり、これは結構致命的だ。

というわけで現在LR文法でタイルを実現する方法を考え中である。しかしそもそも LR 文法は文章を左から右に順に処理していくことを想定しており、タイルのように解析し終わった文の真中に別のタイルを挿入しようと思ったときの処理がうまくいくか分からない。 -- 2002-12-29

タイルスクリプティングとの結合

先週くらいからタイルスクリプティングと言語ゲームとの結合を行っている。当初標準のタイルスクリプティングをそのまま流用しようかと思っていたのだが、結構複雑でそれは挫折してしまった。ただ、僕が必要としているコードは山盛りそこに存在しているので、美しくないがちょくちょくコピペで済ます事にした。

最初単にアイコンでプログラムが書ければ楽しいくらいの思いだったが、作っていくうちにそれ以上の可能性を感じている。まずタイル同士をくっつける場合、妥当性のチェックを行うのだが、そこで文法のチェックを行える。すなわちそもそもシンタックスエラーが全く起こらない。またそこで同時に構文木も再構築していける。つまりこういうことだ、通常プログラムの解釈というものは、テキストファイルを初めから順に、字句解析、構文解析、意味解析のプロセスを流して行われる。しかしこのタイルシステムにおいて解析は上から順ではなく、タイルを追加/削除した場所だけ局地的に行われる。

最近の Microsoft の開発環境は良く出来ていて、ソースを書いた端から解析し入力支援をしてくれる。そこまで出来るならその場でコンパイルもやってくれよと思うのだが、出来るのだろうか?通常、人間のキー入力は十分に遅いので、途中からコンパイルを行う事により効率が落ちても体感的には全然早いと思う。文字によるソースの場合自由度が大きすぎて大変かな?

さらにそれを発展させて、ビジネスロジックのリアルタイムチェックも行える。僕は前に Perl のシステムを作っているときに、10秒間に1度テストを行うというのを実践したことがある。もちろん別窓で、watch を使ってテストスクリプトを走らせながらプログラムを書いていたのだが、自分のキー捌きとともにエラーが減っていく様子がリアルタイムでわかって面白かった。DB を多用するシステムではデータがムチャクチャになって難しいが、進捗状況を体感できるというのは非常に有用だ。

ただし、実はテストを考えるのが一番難しくて、時間の短縮も難しい。 -- 2002-12-22

TGen の利用

衝突時の戦略→アラートが出てしまう。ShiftingConflictStrategy が使えるか?

標準タイルスクリプティングを利用できるか?

ScriptEditorMorph>>codeString
がコードを生成しているようだ

最初タイルスクリプティングのサブクラスとして実装すれば手間がかからないだろうと思っていたのだが、困難らしいと言うことがわかってきた。まず、タイルスクリプトは行志向のシステムと言うことで、文脈自由文法をそのまま使う事が出来ない事。アクセプトするタイルの種類を ifTrue: しまくって検査しているので、拡張しにくい事がある。うーむダサいがコピペで作るか。。。-- 2002-12-09

言語ゲームの応用

とりあえず音楽言語を作る。
音楽言語を作るにあたって問題なのは、時間をどう表現するかだ。電卓をしたりフラクタル図形を描くぐらいなら生成したノードに実行ブロックを持たせてまっすぐ実行すれば良いけど、一瞬で終わってしまっては音楽にならない。だからといってゆっくりプログラムカウンタを動かすような形にすると、和音{ドミソ}{ミソド} のような文法を作りたいときに和音が表現できなくなっちゃう!
これは逐次的にプログラムを実行するというよりはコンパイラ的な、しいてはノマド的な考えが必要なのだろうか? -- 2002-12-08

プログラミング言語 Pipe

例えばここにプログラミング言語 Pipe があったとしよう。Pipe は sed のようにストリームしか扱えない。世界のあらゆる現象をすべてストリームとして扱い、入力し、出力する。C, java, haskell それらの言語がみんな入出力を厄介物とし、おまけのように言語機構に取り入れているのに対して、Pipe にとっての入出力は一級のオブジェクトだ。だって、それしかないから。ストリームは一本だけではなく、何本も束ねたり、haskell の zip 関数のようにちょっとずらして重ねる事によってフィードバックループを作る事が可能だ。フィードバックループ(再帰)はおそらく Pipe にとって最も基本的な制御機構になるだろう。

チューリング機械は元々無限を対象としていたのに、有限の時間に解が必要だった初期の顧客である軍の要請からか、コンピュータ言語の今のモデルは有限で美しいメモリ空間にライブラリとして外部の汚い世界を組み込んでいるかのような構成をしている。世界は少なくとも人間が想像しているよりは無限に近いので、この無理矢理さは捨て置けない。だから最初から無限をベースにした言語を作った方がいいんじゃないかなと思う。デフォルトで無限ループになっている Squeak のタイルスクリプトは、もしかしたらそんな発想が底にあったんじゃないだろうか???
http://www.klic.org/software/klic/index.ja.html - ストリーム言語って書いてあったけど

パイプを第一級のオブジェクトだとするならば、ストリームもパイプとなるだろう。もちろん、ストリームの中にパイプ自信を流す事も出来るし、「あるストリームを流されているパイプ」もまたパイプといえる。つまりパイプのカリー化だわな。最初のイメージとしては、UNIX のシェルが先行事例として役に立つ。基本オブジェクトは数字ではなく、/dev/null のようなストリームになる。

Pipe にとってのプログラミングとは、プログラムを表現する文字列を Pipe コンパイラに渡し、結果として目的のパイプ(プログラム)を得る事である。Pipe コンパイラ自身ももちろんパイプであり、プログラムを動的に生成する事が出来る。Pipe プログラムはトボロジックな構造だけを持ち、内部状態を持たないので、ある意味関数型言語だと言える。事実パイプをそのまま関数と言い換えても良さそうな物だが、本質的に無限を扱い、有限はありえないと考えるので、そこんとこ強調する為にパイプにこだわる。

果たして、Pipe は一体何の為の言語なのか? C が OS を記述する物であり、prolog が論理を記述する物であるように、Pipe にも適応されるべきジャンルが存在する。僕は Pipe を、情報の意味を解釈し、さらに豊かな情報を生成する魔法のパイプを作る為のツールにしたいと考えている。そう、Pipe は言語ゲームのもう一つの姿なのだ。Pipe はノイズとは何でありシグナルとは何であり、乱数とは、美とは何であるかを定義するものになると思う。-- 2002-11-17

パイプとは、結局関数合成の事なのではないだろうか?関数合成と聞くと数学チックで鬱陶しいのに、パイプと聞くと工事みたいで楽しくなる。
3を | 半分にして | 切り捨てる
たとえばこういう言語があって、(日本語MINDみたいなものか?)「半分にして」「切り捨てる」をそれぞれ引数1の関数とみなす。ってこれは単にスタック型言語の事か? -- 2002-12-08

ランダム

ある情報を表現する為のプログラムの長さが、その情報と同じくらい長くなってしまったら、その情報の事をランダムと言う。らしい。これはここ数年で知った最もビックリする知識の一つです。だけど情報を表現するプログラムの書き方なんていくらでもあるし、そんなあいまいな物を数学的対象に出来るものなんだろうか? と疑問をもちつつランダムについて勉強しています。言語ゲームも「ある情報を表現する為のプログラム」といえないことも無い。言語ゲームはBNFを元にしているけど、BNFでも扱えない情報の範囲が分かっているなら知りたいところです。しかし数式と言うのは何でこんなに難しいのだろう。。。

再帰

単なるストリームとバッファだけではコンピュータは作れない。に書いた文章は再帰の事を忘れていた!なぜ遺伝情報をすべて含まない DNA が生物の形を作り出す事が出来るのか?中学の時に習ったのだと思うけど、それは卵子が自分自身の作った環境を情報として受け取り、手足を作る位置の手がかりとする誘導と言う作用のおかげだ。つまり、ギターの歪を作り出すあのフィドバックループのように、情報が情報を作り出す。
コンピュータと文学の強力さは記号にある。記号は過去を参照し、元の情報を豊富にする。特に強力なのは自分自身を参照する場合だ。記号による自己参照は決して単なる無限ループではなく、単純な情報をどんどん複雑にしてゆく。チューリングはこの姿を1本の無限テープと有限のメモリで表現した。世界を1次元と考えると、僕らと記号の精神は割り切れる目盛りの上ではなく、√2やPIのような、気持ち悪い位置にあるに違いないと思う。

乱数

小学生の時、友人からポケコンを貰ってゲームを作ろうとしたのですが、そのときはたと困りました。そのポケコンには乱数の関数が無かったのです。
仕方が無いから自分で作ろうと思ったのですが、ここで意外な問題が発生したのです。プログラムした通りにしか動かないコンピュータに乱数を発生させる事なんて原理的に無理だった!
まーそれでも現実には乱数を使ったプログラムは世の中ゴマンとあるわけですが、それらは擬似乱数といって、乱数を計算で出しているのです、乱数を計算で出すとはシュールな表現ですが、出来るだけデタラメっぽく見える数列を探して、それを計算で次々求めて行きます。
で、僕もそれをやろうと思ってあることに気が付きました。計算で求められる数列という事は、ある数の次の数が必ず決まっているという事です。という事は、10までしか数を数えられないコンピュータがあったとしたら、そのコンピュータは10個以上の乱数を発生できないという事です。
という事は、やっぱり下でも書いたように、メモリと出来る事の大きさは本質的に関係があるということか???いや、しかし、パイや、ルート2なんてのは数文字しかないのに、無限の乱数を生成する事から、アイデアでカバーできる事なのか?
この謎は、数年後カオスという考え方や、DNA に遺伝情報の全てが含まれているわけではないという事を知ったときに再燃するのですが、僕の中では結局結論づいていません。
言語ゲームも、そういう謎を探求するツールになったら良いなと考える次第です。

ストリーム

プログラムの書き方の中に、ストリームというものがあります。コンピュータのメモリは有限ですから、データを解釈する為には長さを制限しなくてはいけません。しかし、解釈したいデータの長さが決まっているなんて事はめったに無く、場合によっては無限なんて事も考えられます。
こういう場合に、全部一度にメモリに入れないで、端っこから読んで少しずつ処理しようというのがストリームの概念です。少しずつ読むための入れ物のことをバッファと呼びます。

ここで、人生これ即ちストリームではないかと思ってしまいます。人生を一度に体験する事は出来ませんから、僕らは少しずつ時間軸上を移動している事になります。そうするとバッファは人の器の大きさと言う事になるでしょう。そうなると気になるのが自分のバッファの大きさ。または、バッファは最低どれだけあれば足りるのだろうかという事です。
万能チューリングマシンの定理という物があるのですが、これによるとあるコンピュータは他のコンピュータの真似を出来るから、バッファの大きさは本質的な問題では無いという事になっているらしいです。しかしチューリングマシンと人生の違うところは、チューリングマシンにおけるストリームが逆方向に移動可能で、しかも読み書き可能であるのに対して、人生のストリームは過去に引き返せないという点です。こういう場合、バッファの大きさが本質的な問題になるのかどうか知りたい。
ちなみにこれは単なる夢想的な設問ではなく、例えばネットワークプログラミングにおいては過去に戻れないストリームなんてあたりまえなので、このような
におけるプログラミングのモデル化は結構重要なのではないかと思います。

関数型言語について

言語ゲームを作っていて思ったのだが、これって関数型言語に似ていない?!
実行順序に依存しない部分や、再帰を使うところなんかがそっくりです。そう思って、今 Haskell の勉強しています。
やり始めてみると、Perl で鍛えた僕の頭には結構面倒くさいです。数学的な問題にはともかく、こんなのでほんとうに実用的なプログラムがかけるのだろうか?
ただ、入出力に関係するノマドという考え方は非常に面白い。
関数型言語は静的な性格を持っていて、ある問いには一つの答えを必ずという性質を持っている。だからマウスやキー入力みたいな、何が来るか決まらないデータを扱いにくい。だから、入力に対する答えを直接プログラムするのではなくて、ある入力に対してこう答えるプログラムを答えとして返すという方法をどうやら取るらしい。うーんわかるようなわからんような。

Link to this Page

propella home