Hatena::ブログ(Diary)

takuto_hの日記 このページをアンテナに追加 RSSフィード

2008-10-22

Cyan, Yet Another New language

プログラミング言語Cyanを公開しました。

これは、私がU-20プログラミング・コンテストに応募し、個人部門で賞をいただいた作品です。

Cyanは「さいあん」と読みます。Lispマクロを持ち、Python風のインデントによってブロックを表します。インスタンスベース・オブジェクト指向や継続といった概念を取り入れています。

以下に簡単な紹介を載せます。詳しい説明は、Cyanリファレンスマニュアルなどをご覧ください。

S式マクロの分離

Cyanのもっとも大きな特徴は、LispS式マクロの分離を試みたことです。

mac(while)^(test, body):
  `loop:
    if(!?test): break()
    begin(?body)

これは、準クオートを用いて記述したwhileマクロです。単純なマクロはこのように簡単に記述できます。

これが可能なのは、式がすべてオブジェクトだからです。関数呼び出しも、演算子式も、すべてが操作可能なオブジェクトです。つまり、Cyanはコードとデータを区別なく扱えるのです。

もちろん、もっと複雑なマクロも記述できます。興味のある方は、マクロの使用法をご覧ください。

インデント・ブロック

上の例でも用いましたが、Cyanはインデントによってブロックを表します。

i = 0
while(i < 10):
  say(i)
  i++

先ほどのwhileマクロはこのように呼び出します。

また、if関数の呼び出しは特徴的です。

if(x == 0):
 say("then_body")
 say("x == 0")
 else:
  say("else_body")
  say("x != 0")

elseというシンボルを使って、2つ目のブロックを渡しています。このようにして渡されたブロックは、キーワード引数として受け取れます。

インスタンスベース・オブジェクト指向

Cyanはインスタンスベース・オブジェクト指向によってプログラムを記述できます。スロット、メッセージ、ペアレントへの委譲という三つの概念によって構成され、動的にメソッドの追加・変更が可能です。

詳しくは、インスタンスベース・オブジェクト指向をご覧ください。

継続

Cyanには、Schemeなどの言語で見られる継続が実装されています。loopマクロの中で使えるbreakやcontinue関数から戻るためのreturnも継続が代入された変数です。次のようにして使われています。

mac(loop)^(body):
  `begin:
    continue := []
    callcc^(cont): continue = cont
    callcc^(break):
      begin(?body)
      continue()

Cyanの処理系は、継続の仕組みをなるべく単純にするため、少し変わった実装をしています。興味のある方は、ぜひご覧ください。

最後に

現在のCyanには、ファイル出入力などの実用的な機能はほとんど実装されていません。ですから、おもちゃのような言語だと思って遊んでいただけるとうれしいです。

ita-wasaita-wasa 2009/10/23 23:23 すごいです!
Lisp は不勉強にてあまり分かりませんが、 python っぽい(インスタンスベース)オブジェクト指向ってだけでおおぉ!!とおもってしまいました。継続サポートも言語レベルで必要な範囲だと思うので素晴らしいですね。楽しみにしています。

babanba_nbabanba_n 2014/03/17 23:16 すいません、メールで送るつもりだったものなので長文になってしまいます

普段はRubyで業務を行っていますが
勉強のためにCyanをベースに処理系を書いている最中です
Cyanという言語を再び理解するための良い機会になったのですが
その中で幾つか疑問に思っていたことがありますので
すこし質問をさせて下さい

質問1.中間表現をS式にしなかったのは何故でしょうか?
Cyanでは「1.(+)(2)」 の様な中間表現に変換されますが
返還後の中間表現としてS式を使わなかったのは何故だったのでしょうか?
S式は大文字小文字の区別がないという致命的な欠点がありますが
LL(1)で解析出来ますし今まで得られた知見を使えるしS式の方が良かったのではないのだろうかと感じました
当時どう考えていたのか教えていただければ幸いです

質問2. Messageオブジェクトは必要だったのでしょうか?
実際に動きを追って行ってみると
メッセージオブジェクトで、メッセージの中継を行わなくても
全く同じ動作が出来たようです
MessageObjectを通過する事の意味は何だったのでしょうか?
正直、Smalltalkと真のオブジェクト指向に関する知識が甘いのですが
今回入れる必要があったのかな?という風に見えましたが
実際に作ってみたときはどう感じたのでしょうか?

3.リフレクション
メソッドの呼び出しがすべてリフレクションになっているのは
速度面でおそろしい低下を招くと思うのですが

YellowやIbisなどをサッと覗いてみると
今はLispの様な、最小要素を突き詰めていく方向に流れているように見えるのですが
当時はどう考えてCyanのコンセプトに至ったのか
細かいところは語られず終いな感じがします
良い機会なので当時を振り返って、Cyanとして成功したと思っている所
逆にあの段階で開発を終了させた失敗と感じたところを教えていただければと思っております

takuto_htakuto_h 2014/03/18 09:01 id:babanba_n さん、コメントありがとうございます。

質問1.中間表現をS式にしなかったのは何故でしょうか?
中間表現をS式にせずともLispのマクロは実装できるということを示すための言語だったからです。アイデアを提示するためのものなので有用性は二の次です。
今は構文がS式でないことの必然性やLispのマクロの万能性には少々懐疑的なため、より良い方法があるのではないかと思っております。具体的な案は残念ながら持ち合わせておりませんが。

質問2. Messageオブジェクトは必要だったのでしょうか?
Symbolオブジェクトのことでしたら、internすることによって同値性の比較が同一性の比較として行えるようになるというメリットがあります。
Messengerオブジェクトのことでしたら、メッセージ送信の構文木としての中間表現です。非S式の構文でLispのマクロを実現するために必要です。また、構文木もオブジェクトであるというSmalltalk的オブジェクト指向を体現しているともいえます。

質問3.リフレクション
簡潔に書くことを優先したために速度低下を招いてしまいました。実用にはあまりこだわらずあくまでコンセプトを示すものだったため、楽に実装できることが優先でありマクロの実装方法など処理速度を完全に無視したコードが含まれています。実用にあたってはあまり参考にすべきでない部分が多いと思われます。

「非S式の構文でもLispのマクロは実現できること」「レイアウト構文の可能性」「プロトタイプベース・オブジェクト指向や継続といった概念の面白さ」を示すのには成功しました。また、私が初めて作成し公開した本格的なプログラムだったため、色々と勉強にもなりました。

開発を終了したのは私が目指す「美しい言語」ではないと感じたためでしょうか。「美しい」は主観ですので説明しがたいのですが、直感的にこれではダメだという感じです。今はプログラミング言語の理論と実際のプログラミングの現場と言う実用の両輪を学んで長いスパンでまだ形となっていない新たな言語を作成していきたいと思っております。

当時はまだ未熟だったこと(もちろん今も勉強中ですし一生勉強だと思っております)から設計も実装もこのように疑問の挙がる点が多いですし、若輩者が勢いで作った作品の一つとしてとらえていただけるとありがたいです。

babanbaban 2014/03/19 00:41 思っていた以上にお早い回答ありがとうございます
未熟者なりにひとつひとつ読ませていただきましたが
回答された理由一つ一つが、妥当だなと感じられるものでした
今回は、なんだか生意気な質問をした様に聞こえのでしたらスイマセン
Cyanを参考に開発をしてみたのも
私の知っている範囲で簡潔さと読み書きしやすさのバランスが一番良く取れている言語だったと感じたからなので
そのぶんよく知りたかったものだったのは分かってやって下さい

はてなユーザーのみコメントできます。はてなへログインもしくは新規登録をおこなってください。