Rubyist のための他言語探訪 【第 9 回】 日本語プログラミング言語「なでしこ」

書いた人:クジラ飛行机

はじめに

こんにちは。日本語プログラミング言語「なでしこ」開発者のクジラ飛行机です。情報通の Rubyist の皆様なら、名前くらいはご存知でしょうか? なでしこは、日本語に近い文法を用いてプログラムを作っていくことができる言語です。

日本語プログラミング言語については、その面白さに加えて、必要不要で論争があったり、「こんなの日本語とは言えない」などなど、時には議論の的になります。この機会に、日本語プログラミングについて、より多くの人が日本語とプログラミングに関して興味を持ってくださる事を期待して、日本語プログラミング言語「なでしこ」について熱く語らせていただきます。

なでしこについて

なでしこは、私が、IPA2004 年度未踏ユース採択プロジェクトにて開発した言語です。それまで、とある会社の片隅で一人でコツコツ作っていた「ひまわり」という言語を大幅に改良して作ったものです。「ひまわり」というのも、日本語のプログラミング言語ですが、主に、日々の雑用を片付けるためのちょっとしたマクロ言語として開発したものです。

日本語プログラミング言語について

対象ユーザーに関する論争

これまで多くのプログラマーの皆さんから「日本語プログラミング言語、面白いと思うけど、自分では使わないなぁ〜」と言われ続けて来ました。その通り、はじめから、Rubyist の皆様に、使っていただこうとは考えておりません。もともと、なでしこは、これからプログラミングをはじめる「プログラミング入門」以前の方に使ってもらえたらいいなぁと考えて作ったものです。

私が考える日本語プログラミング言語の対象ユーザーは、「プログラムって何? それって便利なの? 面白そうだから、なんかやってみたいなぁ……」というプログラミング以前の人、および「日本語万歳! 日本人なら母国語の日本語でプログラムするべきだ!」という素晴らしい思想を持つ硬派な人です。

日本語が理想的なケース

とにかく、プログラミング言語は難しくなりすぎました。今では、コンピューターを利用する人のほとんどが、プログラミングと無縁です。ですが、ちょっと複雑な処理を片付けたり、毎日同じような作業を片付けるのに、プログラミングができるとできないでは、仕事の作業効率に雲泥の差が出ます。

そんな時、「ちょっとやってみたいだけ」なのに、構造化プログラミングや、オブジェクト指向など、もろもろの決まりごとを学習しなくてはならないのは、まったくナンセンスです。覚えることが多すぎます。とにかく、目の前の仕事を手軽に片付けたいだけで、これから書くプログラムの美しさや、プログラミング言語に関する思想など関係がありません。

つまり、昔の BASIC みたいに、なんとなく適当に「書けば動く」という状態が理想的なのです。そして、さらに、それが、日本語に近い文法を持つ言語であって、なんとなく数行のプログラミングをコピペして数文字だけ修正したら、仕事が完遂できたとなれば、言うことがありません。

私は根っからの日本語プログラミング言語のファンです。毎日、何かしら日本語でプログラムを書いたり利用したりしています。しかし、100 行以上のプログラミングを書くことは、ほとんどありません。ここから考えると、日本語を使って理想的なケースというのは、バッチ処理的な処理、手順の流れを簡潔に記述したい処理などに限られてくるかもしれません。

デメリット

これは、なでしこのデメリットではあるのですが、あまりに日本語の文法にこだわっているため、どれが関数でどれが変数なのか、一見して区別がつきません。もちろん、C 言語のように、「strcpy(a,b)」のような関数的な表記もできますが、これでは、あまり意味はありません。

できるだけ、名詞は変数、動詞は関数と日本語の意味に基づいた名前規則を意識すると、変数と関数の区別もつきやすくなりますが、これには文法的な強制があるわけではないので、気をつけていないと、逆に読みにくいプログラムになってしまう可能性もあります。

また、「漢字への変換が面倒ではないか」との意見もよくあります。ですが、普段、友人に電子メールを書くとき、漢字の変換が面倒なので、英語で書いたなんて例はあまり聞いたことがありません。既に漢字入力プログラムは十分に賢いので、それほど、日本語の変数関数名を使うことに面倒に感じることはありません。それどころか、難しい英単語を覚えるよりも、「覚えやすい」「馴染みやすい」という声の方が多いです。

ただし、単純な計算式がたくさん出てくるプログラムで、変数名に長い綴りの単語を採用した場合に、非常にタイプするのが面倒に感じることもあります。しかし、これは、英語の単語の場合も同じでしょう。

実装に関して

次に実装に関することについて書いてみます。日本語プログラミング言語には、既に様々な言語が存在します。老舗の「Mind」に続いて、TTS、言霊、ひまわりなどです。それぞれの言語ごとにユニークな手法を用いて日本語プログラミング言語を実現しています。ここでは、皆さんが、日本語のプログラミング言語を作ってみるという観点から、なでしこの実装を紹介します。

単語 (トークン) の区切りに関する問題

日本語プログラミング言語を作る上で、一番初めに悩むことは、どうやって、日本語を単語 (トークン) に分割しようかという問題です。日本語は英語と違って、単語がスペースや句読点で区切られていませんので、文脈を見て区切る必要が生じます。どうやって、トークンを区切ったら良いのでしょうか?

諦めるという選択

老舗の「Mind」や私が以前作った「ひまわり」では、この問題を完全に諦めています。プログラミングを行うユーザー自身が「分かち書き」をすることでトークンの区切りを明確に示してもらうのです。例えば、『変数Aに3を足す』というプログラムなら、以下のように、ユーザーがトークンの区切り位置に、読点やスペースを書かなくてはなりません。

 変数Aに、3を、足す。

当然ですが、この方法は原始的ながら、一番正確に解析が行えます。このプログラミングに慣れると、プログラム以外でも、日本語の文章を書くときにやたらと、読点が増えてしまうという欠点があります。

形態素解析という選択

次に思いつくのが、「分かち書き」というキーワードから、形態素解析を用いた本格的な日本語の解析です。kakasi や MeCab など、オープンソースの形態素解析エンジンも存在します。この方法は昔ほど実装に手間がかからないと思います。しかし、デメリットとして、(インタプリタの場合) 構文解析に時間がかかってしまうことや、巨大な辞書を同時に配布しなくてはならないという問題があります。

また同時に、巨大な辞書を使う割に、完全に正確な場所でのトークン分割ができないという問題もあります。「プログラムがなんとなく動くのだが誤作動が多すぎる」というのでは困りモノです。ですが、プログラミングの入門用、教育用だけに使うソフトウェアなら、それでも問題ありませんし、用途を限定することで実用に耐えるものになる気がしています。以前、カーナビやケータイのボイスコマンド機能が面白くて、特に必要もなく使って遊んだものですが、これらは、用途が限定されているので、適当に言っても言葉の揺れを吸収して、なんとなく仕事をこなしてくれます。

助詞区切りという選択

なでしこを作る際に、トークンの区切りに関しては、ずいぶん悩みました。そして辿りついたのが、「助詞区切り」という方法です。日本語の文章は、だいたいのところ、助詞で区切られています。先ほどの『変数Aに3を足す』という例でも、「変数A(に)3(を)足す」と、必ず、単語の区切れには「に」「を」などの助詞が用いられています。そこで、この助詞 (は|の|が|から|まで|に|へ|を|で|など) を句読点のようなデリミタ (区切り記号) と見なして、トークンを区切ることにしたのです。この方法は、ほとんどの場合、問題なく機能しました。

ただし、うまくいかない場合もあります。変数名の中に「の」「は」などの助詞を含めたい場合です。例えば「リンゴの値段」の場合などです。この場合は、仕方ないので「リンゴ値段」と縮めたり「リンゴノ値段」とカタカナにしてもらったりします。また、根本的な解決策として、トークンを区切るとき、例外語句を設定しておく方法もあります。

構文解析

トークンを区切った後は、Forth 言語に似た処理を行います。つまり、トークンを順に読んでいって、変数や定数だった場合、スタックにデータを積んでいきます。そして、関数だった場合には、必要な数だけスタックからデータを下ろして、関数を実行します。これは、日本語の文法が、計算機の処理において効率的な、逆ポーランドに近いことを利用しています。

例えば、以下のような入力を例に取ると

 4と|5を|足して|変数Aに|代入する

次のような操作が行われます。

 入力      スタック操作
---------------- ---------------------------------------------
 4(定数)    スタックに「4」を乗せる
 5(定数)    スタックに「5」を乗せる
 足す(関数)   スタックから「4」と「5」を下ろす
          下ろして計算の結果「9」をスタックに乗せる
 変数A(変数)  スタックに「変数A」を乗せる
 代入(関数)    スタックから「9」と「変数A」を下ろす
         変数Aに9を代入する

ただし、なでしこでは、トークンを区切った後、すぐに実行するのではなく、一度、構文木を作ってから実行するようにすることで、実行速度が出るように工夫しています。ただ、このあたりは、日本語とぜんぜん関係なく、当然必要となる処理です。

ですが、なでしこの前に作った「ひまわり」では、ぜんぜんそんな工夫をしていませんでした。とにかく動けば良いと思っていましたし、マシン速度が十分に高速な現在では、インタプリタの高速化に時間を割くよりは、ライブラリの充実に時間を割いたほうが、ユーザーが喜ぶかもしれません。

制御構造

構文をどのように実装するのかは、一番言語作者の好みが出るところかもしれません。なでしこでは、「日本語として読める」という点に留意して制御構文を考えました。この時、構文レベルにインデントを用いることにしました。これは、スクリプト言語の Python を参考にして作りました。プログラムがより日本語っぽく見えるためにはどうしたら良いか考えて採用しました。

しかし、Python ライクなインデントによる構文表現は、賛否両論のあるところです。日本語の文章でインデントによってレベルを下げることは一般的でないので、逆に不自然に見えてしまうという意見もありました。Ruby のように、end で制御文を閉じるようにするようにした方が良かったのかもと思います。

以下、参考までに条件分岐の「もし」文と、繰り返しの「回」文を紹介します。

「もし」文

「もし」文は、if にあたる制御構文です。

もし、天気が「晴れ」ならば
  洗濯を干す
違えば
  乾燥機を使う

「回」文

「回」は指定回数だけ繰り返し実行する制御構文です。

3回
  「わん」と表示。

言語設計の楽しみ

「なでしこ」は「ひまわり」を元に、日本語プログラミング言語の道を追求して来たのですが、言語が完成してしばらく使っていると、いろいろな改良点を思いつき、機会があれば、もっと完成されたものに改良したくなるものです。

言語設計の楽しいところは、制御構文を考えたり、使いやすい機構を考えたりという部分です。加えて、関数の名前のネーミングだったり、ちょっとした造語を考えたり、センスが問われる部分もあります。「なでしこ」では、アプリケーションのメインウィンドウのことを「母艦」と呼んでいるのですが、ユーザーの間でちょっとした話題になっています。

このように、言語設計は、詩人としての感覚も必要になってくる部分もあります。プログラミング技術だけでなく、尖った感性も磨いて、今後も便利で面白い言語に育てていきたいと思います。

著者について

ウノウ (株) プログラマー。 1976 年生まれ。中学生の頃、MSX というパソコンに出会い人生が一転。 ゲームや音楽のプログラミングに没頭。 現在は、ソフト企画「くじらはんど」にて、オンラインソフトを多数発表している。 代表作は、ドレミで作曲できる音楽ソフト『テキスト音楽「サクラ」』や『日本語プログラミング言語「なでしこ」』など。 著書に『‘日本語プログラミング言語「なでしこ」ガイドブック’』や『‘ゲームプログラミングで学習する ActionScript (Flash8/MX2004)’』など。 日本中に、プログラミングの楽しさを伝えるため日々奮闘中。 ホームページ→ http://kujirahand.com

バックナンバー