yojikのlog

yojikのブログです

イケてるしヤバい言語 REBOL

ある日ふと思い立って調べてみた、イケてるしヤバい*1言語REBOLについて紹介します。

REBOLは、 Relative Expression Based Object Language 「相対的な表現をベースにするオブジェクト言語」の略です。よく意味わからん。

Wikipediaによると、

1997年にリリースされたREBOLは、カール・サセンラスが20年に渡って設計したものである。サセンラスは AmigaOS の主要アーキテクトであり、REBOLの設計にあたっては、表示的意味論の知識に基づいて、LISP、Forth、LOGO、Self といったプログラミング言語の概念を利用した。

引用元:REBOL - Wikipedia

大雑把にいうと、LispやForthやLOGOやSelfに似たスクリプト言語です。ここからダウンロードできます。最新バージョンはオープンソースライセンスになっています。

REBOLのイケてるしヤバいところ

それではREBOLのすごいところを軽く紹介していきたいと思います。

つくった人がすごい

 1985年にデビューしたAmiga OSは、マイクロカーネルアーキテクチャを採用、設計において他のコンシューマ向けOSの数歩先を行っていた。プリエンプティブマルチタスクに対応し(略)先進性は明らかだろう。そのカーネル(Exec)の開発にあたった中心人物が、Carl Sassenrath氏だ(略)現在Sassenrath氏は、REBOL Technorogiesで「REBOL」というプログラミング言語の開発に従事している。

引用元:Amiga、REBOLの思想を引き継ぐスクリプト言語「Red」 - builder

AmigaOS は当時のフロッピーに収まるほどのサイズで、業務用(日本有名な例ではウゴウゴルーガのCG製作)に使われるほど高機能でした。マイクロカーネルOS Mach の開発開始が1985年ですから、いかに先進的なアイディアの持ち主かがわかります。シンプルで低フットプリントのソフトウェアで最大限の効果をあげるのが上手い、というイメージですね。今回のREBOLランタイムも300kbほどのサイズです。

目的がすごい

REOBLの目的は、「インターネット上のあらゆる機器間で情報がどのように格納され、交換され、処理されるかを表す新たなアーキテクチャを提供することである。すなわち、人間と機械の間の情報の意味論的交換に使われることを意味する」らしいです。

つまり、XMLやJSONのようなメッセージ交換のための言語(かつ人間が読みやすい言語)でありながら、スクリプト言語として実行可能な言語でもあるということです。他のマシンに移動して処理をおこない結果を持って帰ってくるスクリプトとか、ある意味エージェント指向的な未来像が浮かびます。インターネット全体を分散コンピュータのように使えるようにするイメージは初期のJavaも持っていましたが。。。

記述力がすごい

凄い目標を持っていても、スクリプト言語として手軽に使えなければ意味がありません。その点REBOLにはそれなりの記述力があります。

「Webページを開いてボタンを押すとemailで送るパネルを表示する」ワンライナー

view layout [u: field "user@example.com" h: field "http://" btn "Send" [send to-email u/text read to-url h/text alert "Sent"]]

カレントディレクトリにあるファイルをftpでアップロードする

foreach file load %./ [if not dir? file [write/binary join ftp://user:pass@example.com/ file read/binary file]]

このように便利な関数が最初からビルトインされていてワンライナーでいろいろできます。英語の文章のように読める点もグッド。

また上記例にある、%./ はファイル型のリテラルftp://user:pass@example.com はURL型 のリテラルです。email型など普通のコンピューティングで使いそうな型を取り揃えています。これもプログラムが短く読みやすくなるのに一役買ってるようです。

でもそれって拡張性なくてオモチャ言語っぽくなりそう… と思われるでしょうが、後述するようにREBOLは全く別の次元で柔軟性を確保しているのです。。

REBOLプログラムの例

コマンドラインインタプリタでは、このような感じで実行できます*2。下の例では関数を定義してsampleという変数に入れ、実行しています。

>> sample: [n: 1 + 3]
== [n: 1 + 3]
>> do sample
== 4

>> n
== 4
  • 明示的な型宣言は必要なし
  • 代入は変数の横にコロンをつけて、右辺に値
  • 実行可能なブロックも変数に代入可能
  • ブロックをdoという関数に渡すと実行する
  • 関数の実行には[]とか余計なものはいらない

ぐらいのことがわかりますね。また関数型言語やプロトタイプベースのオブジェクト指向言語の能力は持っています。

同図像性(Homoiconicity)がスゴい

同図像性とはデータとプログラムがまったく同じ形式でかけるということです。REBOLにはシリーズというデータ構造があり、これは [] で囲まれ、空白で区切られたデータやシンボル等の塊のことです。先ほどの実行可能だったブロックも、配列チックなデータ構造も、すべてこれで表現できます。LispのS式と似ている感じです。

>> ;これも
>> [ 1 2 3 ]
== [1 2 3]

>> ;これも一緒
>> [ 1 + 2 + 3 ]
== [1 + 2 + 3]

先ほどブロックとして紹介していたものも、数値が入ったリストみたいなものも全く一緒です。

>> do [1 + 2 + 3 ]
== 6

Lispは(+ 1 2 3 )とか見つけたらいきなりevalしますが、REBOLはdoに渡した時点で実行lします。話のわかるヤツだ。(ただしインタプリタトップレベルはいきなり実行かも)

doは素直にシリーズの中身を解釈して実行するネイティブ関数ですが、そのほかに複数のシリーズを受け取って並列実行する関数等もあるようです。

とにかくプログラムの並びとデータの並びに全く区別が無いならば、プログラムの一部をデータのように操作することもできます。

>> sample: [n: 1 + 3]
== [n: 1 + 3]

; sampleの要素の3番目の「+」を「-」に変える( /インデックスで要素を操作できます。ちなみに1オリジン)
>> sample/3: '-
== -

;実行
>> do sample
== -2

>> n
== -2

>>

このようにデータとプログラムの境界線は全くありません。

parse関数がすごい

シリーズの中の値やワードを処理するための強力なparse関数が用意されています。これを使ってマクロ(REBOLではdialect)を作成できます。

スケジュールを表現するための特殊なDSLをワンライナーでパースする例です。(細かく説明するには余白が足りない。。ハートで理解お願いします)

>> rule: [some ['when set time time! | 'where set place string! | 'who set person [word! | block!]]]

whenのあとで続く時間型をtimeに代入 or whereの後に続文字列はplaceに whoのあとに続くワードかブロックはpersonに代入する

>> parse [ Who [yojik1 yojik2]  where "Downtown Center"  when 9:30 ] rule
== true
>> time
== 9:30

>> person
== [yojik1 yojik2]

ね、簡単でしょう?

DSLが書きやすい

つまりREBOLは、

REBOLはコンテンツ依存言語であり、ダイアレクト(dialect)と呼ばれるドメイン固有サブ言語をサポートしている。例えば、return という単語の解釈がコンテンツによって変わることを見てみよう。通常、return は関数を完了して呼び出し元に値を返すのに使われる。しかし、Visual Interface Dialect (VID) では、return という単語があるとレイアウトエンジンが改行(carriage return)と解釈し、レンダリングペンを次行の先頭に持っていく。REBOLプログラマは独自のダイアレクトを生成でき、既存のREBOLの単語に別の意味を付与することができる。

引用元:REBOL - Wikipedia

目的別に小さな言語を利用することによって、シンプルなプログラムを作成するのです。

以下のようなダイアレクトがあります*3

  • do ダイアレクト - REBOLの通常の do 関数が理解し解釈できる(ネイティブ)。
  • reduce ダイアレクト - doダイアレクトで結果を集めるよう変更したもの(ネイティブ)
  • compose ダイアレクト - reduceダイアレクトで括弧だけを評価するよう変更したもの(ネイティブ)
  • function spec ダイアレクト - 関数ヘッダ記述に使われるダイアレクト(ネイティブ)
  • parse ダイアレクト - バッカス・ナウア記法風の文法規則を記述するためのツール(ネイティブ)
  • VID - GUI用ダイアレクトで、layout関数として実装されている(mezzanine)。


アプリケーションプログラマも、自分達のシステムのドメインにあわせたダイアレクト(いわゆるDSL)を作成してシステムの再利用性と記述しやすさを確保することができます。

まとめ

REBOLはイケてるしヤバい。

ちなみにREBOLはバージョン2までは商用製品だったこともあり、あんまりメジャーではないです。

以下は、matzにっきからの引用です。

_ まつもと (2004-05-27 21:47)
Rebolという言語があって、まさに括弧なしのLisp(+豊富なリテラ
ル)って感じだったりします(複数戻り値はありませんけど)。

  http://www.rebol.org/

これも最近はぱっとしませんねえ。「言語ビジネスの夢の跡」なん
て呼んだら中の人に失礼かもしれませんが。

LOGOもちょっと似た感じだけど、あれは省略できるのはトップレベ
ルの括弧だけだったような。

引用元:Matzにっき(2004-05-27)

ついでにいうとver2まではまったく日本語対応してないです。このように仕事にはたぶん利用できないですが、プログラムに対する新しい視点が開けるかも、ということで最近調べています。

以上です!

*1:Inspired by http://iketeru-nagashima.com

*2:当たり前ですがファイルを指定しての実行もできます

*3:wikipedia調べ