Wednesday, November 5, 2014

Creating an R list using RsRuby

For the most part rsruby, works as advertised. Where things blow up unexpectedly is when using a Ruby Hash to create an R List object.

irb > require 'rsruby'
irb > ENV['R_HOME'] ||= '/usr/lib/R' 
irb > $R = RSRuby.instance

irb > $R.assign('test.x', { :a => 1, :b => "abc", :c => [8,9] } )
RException: Error in (function (x, value, pos = -1, envir = as.environment(pos), inherits = FALSE,  : 
  unused arguments (a = 1, b = "abc", c = 8:9)

This happens because rsruby treats a trailing Hash as a collection of keyword arguments to the R assign() function. All that metaprogramming magic ain't free, y'know?


The solution is to wrap the Hash argument into an actual Hash storing keyword arguments to the R function.

A quick look at the R help file for assign() shows that it has the following signature:

assign(x, value, pos = -1, envir = as.environment(pos),
            inherits = FALSE, immediate = TRUE)

This means that the Hash containing the R List data will have to be passed as the value argument to the assign() call.

$R.assign('test.x', { :value => { :a => 1, :b => "abc", :c => [8,9] } } )
ArgumentError: Unsupported object ':a' passed to R.

Of course, R cannot handle Symbols unless they are the names of function keyword arguments. This is easy to fix.

irb >$R.assign('test.x', { :value => { 'a' => 1, 'b' => "abc", 'c' => [8,9] } } )
 => {"a"=>1, "b"=>"abc", "c"=>[8, 9]} 
irb > $R.eval_R("print(test.x)")
$a
[1] 1

$b
[1] "abc"

$c
[1] 8 9

 => {"a"=>1, "b"=>"abc", "c"=>[8, 9]}

All's well that ends well!