数日前までの認識
mruby は,Wikipedia によれば「組み込みシステム向けの軽量なRuby言語処理系」とのこと。
要するに電気製品,ロボットなんかに組み込まれている貧弱なコンピューター上で動くようにしたものってことか。
こういう機械用のプログラムでは,C/C++ で書くのは面倒で,Ruby なら簡単に書ける処理がある。しかし,ふつうの Ruby は重すぎて載せられない,そこで……という話なのだろう。
自分には縁のない世界 だと思っていた。
その後,C/C++ のプログラムに処理系ごと埋め込む使い方もあると知った。
「Ruby で書いたら楽なのに」という処理だけ Ruby で書き,それをふつうの C/C++ のコードに埋め込んじゃう,ということらしい。
コンパイルして出来た実行ファイルの中に mruby の処理系が含まれるので,実行ファイルだけ配布すれば動く,というのも利点として大きいのだろう。
こちらも 自分には縁のない世界 だと思っていた。
macOS で動くん?
先月 mruby 4.0.0 がリリースされた。
ふと思った。
mruby って,macOS 上で動くんかな?
動くようだ。
mruby をインストールしておけば,コマンドライン上で
mruby -e "p 1.upto(10).inject(:*)"
とやることで,10 の階乗である「3628800」が表示される。
えっ,ふつうの Ruby と同じ使い方ができるんかっ?
スクリプトをファイルに(たとえば hoge.rb という名前で)保存しておいて,
mruby hoge.rb
として走らせることもできる。ふ,ふつうの Ruby ぽい……。
いや,でもインストールがめんどくさかったりしない?
簡単だった:
brew install mruby
これだけ。
irb 電卓にできる?
なんかちょっとした計算をやらせたいとき,たとえば「A5 判の短辺て何 mm だっけ?」というとき,ワンライナー
ruby -e "p 297 / 2"
を打ったりするよね1。
いくつかの計算を繰り返すときは,irb を起動して式を打ったりする。
こういった「ワンライナー電卓」「irb 電卓」のような使い方はできるのか。
ワンライナーのほうはさきほど見たね。
irb は?
これは mirb というコマンドでできる。使い方は irb と基本的に同じのようだ。
フィルターとか
当然ながら,フィルタープログラムとして使うこともできる。
つまり,標準入力から得たテキストデータを加工して標準出力に出す,といった使い方だ。
たとえば,「テキストデータを与えると,行単位で重複を排除し,ソートして出力」というのは
mruby -e "puts readlines.map(&:chomp).uniq.sort" < in.txt > out.txt
なんて書ける。
制約
mruby は,その性格上,さまざまな制約があるようだ。
たとえば mruby 単体では正規表現は使えない。
ええっ?! いや正規表現が使えないと Ruby の得意分野であるテキスト処理の大半ができんやん?
これはショックだったが,Ruby の正規表現エンジン Onigmo はかなりでかいので(知らんけど),mruby 本体から切り離すのはやむを得ないのかもしれない。
mruby で正規表現を使う手段はいくつかあって,エンジンも Onigmo だけでなく PCRE2 とか複数種類あるようだ。
ただ,私はまだ調べていない。
それから,require も mruby 自体には組み込まれていないようだ。
えええっ?! そんなアホな。
いや,こちらも,何か手段があるらしい。試してないけど。
あと,Ruby の標準ライブラリーなんかも入っていない。
ふつうの Ruby だと,「えっと 100 日後っていつだ?」というとき
ruby -r date -e "puts Date.today + 100"
で分かるのだが,date ライブラリーは使えないらしい(そもそも require ができないんだしね)。
こちらも,何か手段があるのかもしれないが調べてない。
利点は?
しかし,ふつうの Ruby でやればいいことを,わざわざ制約の多い mruby をインストールしてまでやる意味はあるのか?
ある。たぶん。
起動速度
mruby は「軽量」をうたっているだけあって,ふつうの Ruby より処理系の起動が速い。
私が数年前に使っていた Windows 機では,irb を起動するのに,0.5 秒とか 1 秒弱とかかかることがあった。
irb 電卓するのに,これがちょっとしたストレスだった。
いま使っている MacBook Air では,もうそんなことないんだけど。
ためしに,
ruby -e ""
と
mruby -e ""
の時間を雑に測ってみよう。
↓こういう Bash スクリプトを用意して(実行パーミションも与える),
for i in {1..100} ; do
ruby -e ""
done
for i in {1..100} ; do
mruby -e ""
done
以下のようにして実行:
time ./bench_ruby
time ./bench_mruby
私の環境では,
Ruby:
3.09s user 1.25s system 57% cpu 7.486 total
mruby:
0.16s user 0.09s system 87% cpu 0.286 total
という感じであった。桁が違う!
まあ Ruby のほうも十分速いけど,用途によってはこの差が無視できないこともあるだろう。
実行ファイル化
Ruby のスクリプトを他人(たとえば社内の非プログラマー)に使ってもらうとき,「まず Ruby をインストールしてね」というのがなかなかのハードルであったりする。
何年か経って「ええと,いま Ruby のバージョンいくつ入ってます?」と尋ねるのも,なんだかね。
mruby は,実行ファイルを作ることができる。
実行ファイルだけ渡せばよい,というのは大きな利点だ(たぶん)。
ただ,mruby スクリプトがコマンド 1 個で 実行ファイルになったりはしない2。
実行ファイルを作る方法は複数あるようだ。
一つは,上で述べたように,C のプログラムに埋めちゃう方法。
やりたい処理の全てを mruby で書いておき,あとは定型の C コードに放り込むだけでよいらしいので,C 言語を知らなくてもできるぽい(知らんけど)。
やり方は公式サイトの↓ここに書いてある。
https://mruby.org/docs/articles/executing-ruby-code-with-mruby.html#source-code-c
私は試していない。
C のコンパイルオプションも,見ても全然分からん。
私はどこかのサイトに書いてあった別の手段で実行ファイルを作ってみたのだが,(昨日やったばかりなのに)参考にしたサイトが思い出せず,探し出せない。
書いてあるとおりにやれば簡単に出来たのだが。
思い出したら追記する。
感想
mruby おもろいかも。