IO.popenで遊ぶ
IO.popenでRのインタプリタを開いてRubyからRを操作出来ないかなーと思ってちょっと弄ってみました。
ちなみに遊びとかではなくて普通にRubyからRを使いたい場合はRSRubyというライブラリがちゃんとあるのでそちらでどうぞ。
で、とりあえず適当に書いてみたのがこちら。
require 'timeout' def eval_r(io, message) ret = [] io.puts(message) loop do begin timeout(1) do line = io.gets unless line == nil then ret << line else return "" end end rescue Timeout::Error break end end ret.shift return ret.join end #init r = IO.popen("R --vanilla", "r+") eval_r(r, "") # main puts eval_r(r, "a <- c(1,2,3)") puts eval_r(r, "sum(a)") # dispose r.puts "q()" eval_r(r, "") r.close
Rと対話するのに一番の問題は、R側の出力を全て受け取って入力待ち状態になった事をどうやって検出するのか、という点です。このサンプルではとりあえずgetsがタイムアウトしたら入力待ち状態という事にしていますが、これだと処理が重いコードを渡した時に確実に駄目ですね…。しかも毎回タイムアウト待ちするから大変遅いです。あとまぁ"a <- c(1,2,3)"を評価してもirbと違って評価結果が表示されないとか他にも問題は色々と。
やっぱりRSRubyと同様に、C拡張を作ってCからRを直接操作するしかないのかなぁ…