« 2007年10月 | メイン | 2007年12月 »

2007年11月 アーカイブ

2007年11月08日

メッセージキュー事始め in Ruby

ruby でメッセージキューを扱いたく、stomp クライアントライブラリを試してみました。

って、奥さんのエントリとシンクロしているようですが、気のせいではありません(笑)。

1. メッセージキューを起動

ruby の stomp はクライアントだけなので、キュー(サーバ側) は ActiveMQ を使うか、Perl の POE::Component::MessageQueue で立てる必要があります。

今回は奥さんとのメッセージのやりとりが目標なので、奥さんのプログラム( POE::Component::MessageQueue 使用)をそのまま使わせてもらいました。

/usr/bin/mq.pl --data-dir /tmp/mq
プチTIPS: POE::Component::MessageQueue でキューを立てて、subscribe したり、subscribe されていない状態で send したりすると次のようなエラーが出て最初ハマってしまいました。
QUEUE: Message 10 intended for 8 on /queue/test could not be delivered
メッセージが直接的でないのでわかりにくいですが、実は POE::Component::MessageQueue をインスタンス化したときに指定されたストレージへの保存に失敗しているケースが考えられます。 というわけで、自分の場合は DBI-SQLite を入れたらエラーが出なくなりました。

2. ruby stomp のインストール

ruby stomp は gem でさっくりインストールできます。

gem install stomp

この手のライブラリの例に漏れずドキュメントはないので(苦笑)、ソースを読むか、 unit test のコードを眺めるかして心の準備をします。

3. ruby stomp でキューにメッセージを送る

メッセージを送るには Stomp::Connection#send を用います。

require 'rubygems'
require 'stomp'

conn = Stomp::Connection.open "test", "", "localhost", 61613

destination = "/queue/test"

conn.send destination, "message 1\n"

4. ruby stomp でキューからメッセージを受け取る

メッセージを受け取るには Stomp::Connection#subscribe と receive を用います。

require 'rubygems'
require 'stomp'

conn = Stomp::Connection.open "test", "", "localhost", 61613

destination = "/queue/test"
conn.subscribe destination
while true
  msg = conn.receive # キューが空の場合は待ち受け
  puts msg.body
end
# acknowledge する場合。
conn.subscribe destination, :ack => 'client'
while true
  msg = conn.receive # キューが空の場合は待ち受け
  puts msg.body
  conn.ack msg.headers["message-id"] # メッセージ処理後、受け取り完了を知らせる
end

これで POE::Component::MessageQueue を通じて stompy( for Perl ) とのメッセージの送受信が可能であることを確認しました。簡単。

Ruby の中だけで(分散)非同期処理を行うなら、dRuby とかを使うのが楽ちんですが、他プラットフォームも混ざった状態であるなら、stomp もお手頃で良さそうです。


なお、Stomp::Client というクラスもあり、こちらを使えばメッセージ受け取り時のイベントリスナーをブロックで記述できる「はず」なのですが、手元ではどうしても期待通りに動作させることが出来ませんでした。

Stomp::Client も Stomp::Connection を使って実装されているので、ソースを丹念に読めばきっと原因はわかると思うんですが、手抜きして追いかけてません……

2007年11月22日

JSRuby - Javascript による Ruby(っぽい)実装

OreScript時代の幕開け - yukobaの日記
http://d.hatena.ne.jp/yukoba/20071108/p1

巷で OreScript ブームが巻き起こる中、某所ではさらに局地的に Javascript での言語実装ブーム。

××さんが ******* を試作したり、西尾さんが python4js を試作したりして、うーむこんなおもしろそうなお祭りは看過できんでわないか。Ruby 成分の多い中谷としてはここはやっぱ Javascript で Ruby かっ!?

そういえばだれか Javascript でパーサ書いてはったよなあ。それを使わせてもらえば Ruby の構文木をさっくり得られて、ちょこちょこっとインタプリタ書いたら、FizzBuzz くらいなら動くんじゃないの? という思いついてしまったからには、もう作ってみるしか。


というわけで言った者勝ち(笑)の JSRuby をこしらえてみました。

JSRuby テストページ

リンク先のページで簡単な演算や FizzBuzz の実行テストを行えます。一応 IE6, Firefox2, Opera9, Safari3β で動作確認はしてみました。Safari2 では RegExp.rightContext がサポートされていないそうなので動きません(amachang サンクス)。すいません。

コードは <script type="text/ruby"> で埋め込んであるのを拾って textarea に出しているので、編集して実行することもできるようにしてあります。

んが、正直今のところ「 Ruby で書かれた FizzBuzz を実行できる、Ruby っぽい何か」なので、普通の Ruby スクリプトを入れてもまだまず動きません(苦笑)。


実装範囲は

・演算子 +, -, *, /, ==, ..

・演算の優先順位は有効

・数値、文字列リテラル

・代入

・組み込み関数 puts

・if ~ then ~ elsif ~ else ~ end

・配列に対する each メソッド

以上! って本当に FizzBuzz しか見てません……

とはいえ一応代入も if もちゃんと値を返すので、a=b=4 とか puts if x % 2 == 0 then "even" else "odd" end という書き方はちゃんとできます。


実装済みの範囲でも怪しいところはちらほら。特に前者はやばめ。

・パーサの時点で識別子をメソッドか変数か決定してしまっている(ミスった)

・Ruby の型を扱っていない(整数の割り算が実数になる、 .. 演算子が(javascriptの)配列を返す、など)


あと残念ながら、パーサは当初考えていた Gin ではなく、自前で再帰下降パーサを手書きしてます(隠れ左再帰を見つけられず、too much recursion を解消できなかった……)。


まあ半分ネタとはいえせっかく作ったので、上に書いた識別子の問題を解消し、ソースを分割、テストコードを付け、CodeRepos にアップさせてもらえれば、みんなでよってたかってつついてくれて、あれーいつの間にかできてる! とか妄想中w

フル実装は夢としても、どう書く?org の Rubyコードの7割がたが動く、くらいならかなり現実的な気もしますです。


この状態で使ってみようという人はいないと思いますが、簡単な使い方。

jsruby.js を組み込んで、

var parser = new RubyEngine.Parser();
var ruby = new RubyEngine.Interpreter();
ruby.run(parser.parse("puts 2*3+4*5; 9*9*9"))

とやれば指定の ruby コードを実行します。

ruby.run() の返値は最終の式の評価なので、この場合 729 が返ってきます。

また、標準出力の値は ruby.stdout から取り出せます(この場合 "26\n" が入っている)。

標準出力への書き出しは ruby.writeStdout() を上書きすることで変更できます。例えば ruby.run() の前に

ruby.writeStdout = function(st){ alert(st); }

と入れれば、都度ダイアログで表示されます。

2007年11月29日

JSirb - Javascript で Ruby コンソール

JSRubyCodeRepos に登録すべく、「いじってもらう前にここだけはちゃんとしとかんとなー」というところをせっせと作り込んだり、機能テストをちまちま書いたりしています。
これがまあ結構忍耐のいる作業なもので、ちょっと飽きちゃったりすることも。
というわけで気晴らしにさっくり JSirb なんて作ってみました。

JSirb - JSRuby console

名前の通り、Webページに埋め込める JSRuby のコンソール。サンプル( (1..10).each…… ) の入っているテキストボックスで Enter を押すと実行されます。
ただし機能的には前回と変わっていないので、まだまだほとんどの Ruby の機能は使えません(すんません~)。
まあまだあまり作り込んでいないので、出力やエラーがあまあまなのはご勘弁。

2007年11月30日

サイボウズOffice7グッズもらっちゃった

今日、サイボウズ本社の方で Distrubuted Systems の輪読会があったのでのこのこ参加してきました。
で、まあ輪読会の方はどうでもよくて(えっっ!?)、帰りがけにサイボウズOffice7のリリース記念のグッズをもらっちゃいました。ちょっとおもしろかったので、ご紹介。

カレンダーは、普段サイボウズOfficeをご利用いただいている方であれば、「お~、サイボウズ~」とひとうなりしてもらえる感じ? 下の方にカレンダーの画面、じゃなかった、カレンダーの写真も載せておきます。

縮尺のよくわからない10円玉みたいなのは、実はチョコレート。サイボウズ10周年ということで、ボウズマンの裏は 10円玉を模した絵柄になっているわけですね。
これがボウズマンが見得を切っている缶に入っていて、なかなか頑張ってるなー。

ん? でもこのグッズ、どうやったらもらえるんだろう。それは聞くの忘れたなー。
サイボウズの営業さんと接点があれば、「あんなんあるん?」と一言言えばもらえそうだけど(笑)。
「ラボに入って、輪講に参加する」っていうは、ちょっと敷居が高すぎるし(汗)。


JSRuby を CodeRepos に commit しました

とりあえず FizzBuzz が動くだけだった Javascript によるRuby 実装な JSRuby ですが、「全然できあがってなくても、まず公開」という教えもあることですし、とっとと CodeRepos に登録してしまおう~

と思っていたのですが、メソッドの実装まわりや、Ruby のオブジェクトの概念の導入など、構成に大きく影響を与えそうな上にまっさきにやらないといけないことくらいは片付けないとなあ。さすがに全体が1ファイルだと、せっかく手を入れようと思ってくれた人がいても衝突しまくりだし。最低限のテストセットも用意しておいた方が話も早いだろうしなあ。

とごにょごにょ作業していたのですが、ようやくそこらへんが片付いたので、CodeRepos に commit させてもらいました。

http://coderepos.org/share/wiki/JSRuby

ライセンスは JavaScript-XPath にならって MIT ライセンスとしています。

機能的なサポート範囲は先日の「 FizzBuzz が動くだけの Ruby っぽいなにか」から大きく変わってはいませんが、数値や文字列が「 Ruby のオブジェクト」として扱われるようになり、それらのメソッドも実装できるようになっています(サンプルとして Integer#chr と String#reverse は実装済み)。これで「 FizzBuzz が動くだけの Ruby のサブセット」に昇格したんじゃないかと(笑)。
またいろいろ細かいバグも取れてます。

TODO はまだまだいっぱいあって、
・エラー処理
・未実装の演算
・未実装の組み込み関数
・未実装の組み込みオブジェクト&それらのメソッド
・スコープ
・メソッド定義
・モジュール定義
・クラス定義
・……

とまあ道のりは長いのですが、とりあえず「どう書く.org に組み込んでもらって、Ruby のコードならブラウザ上でそのまま動作」というのを目標にしようかなあなどなど夢見ています。

よろしければガンガン commit してやってください。

About 2007年11月

2007年11月にブログ「nakatani @ cybozu labs」に投稿されたすべてのエントリーです。過去のものから新しいものへ順番に並んでいます。

前のアーカイブは2007年10月です。

次のアーカイブは2007年12月です。

他にも多くのエントリーがあります。メインページアーカイブページも見てください。