Class: R::Object

Inherits:
Object
  • Object
show all
Defined in:
lib/R_interface/robject.rb

Overview



Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(r_interop) ⇒ Object





41
42
43
# File 'lib/R_interface/robject.rb', line 41

def initialize(r_interop)
  @r_interop = r_interop
end

Dynamic Method Handling

This class handles dynamic methods through the method_missing method

#method_missing(symbol, *args, &block) ⇒ Object



Raises:

  • (NoMethodError)


131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
# File 'lib/R_interface/robject.rb', line 131

def method_missing(symbol, *args, &block)
  name = R::Support.convert_symbol2r(symbol)

  # Need to raise a NoMethodError when method_missing is called by an implicit
  # call to "to_ary".  The explanation for that is:
  # Okay, I've found the source of the behaviour. IOOperations.puts will attempt to
  # coerce an argument to an array and print its contents, and R::Vector responds to
  # to_ary but returns the empty array which results in no output.
  #
  # Previously IOOperations.puts only checked the type of the argument, and did not
  # attempt coercion, but that meant we didn't match MRI's behaviour and had some test
  # failures in other gems. I'd suggest either removing the to_ary methods on
  # R::Object and R::Vector or implementing them more fully. I see from the comments on
  # those methods that you needed them for RSpec, it might worth seeing if those problems
  # still occur and we can look a better way to resolve those.      
  raise NoMethodError if name == "to_ary"

  case
  when block_given?
    R::Support.new_scope(symbol, self, *args, &block)
  when name =~ /(.*)=$/
    method_missing_assign($1, args[0])
  when name == "eval"
    # R function 'eval' needs to be called in a special way, since it expects
    # the second argument to be an environment.  If the arguments are packed
    # into a list, then there is no second argument and the function fails to
    # use the second argument as environment
    R::Support.r_evaluate(@r_interop, *args)
  when args.length == 0
    # no arguments: 2 options: either a named item of the object or apply the function
    # to the object
    # if name is a named item of the object, then return the named item
    named = R::Support.eval("`%in%`").
              call(name, R::Support.eval("names").call(@r_interop))
    (false === named || !(true === named || named[0])) ?
      R::Support.exec_function_name(name, @r_interop) :
      R::Support.exec_function_name("`[[`", @r_interop, name)
  else
    args.unshift(@r_interop)
    R::Support.exec_function_name(name, *args)
  end
    
end

Instance Attribute Details

#r_interopObject (readonly)

Returns the value of attribute r_interop.



34
35
36
# File 'lib/R_interface/robject.rb', line 34

def r_interop
  @r_interop
end

#statementObject

Returns the value of attribute statement.



35
36
37
# File 'lib/R_interface/robject.rb', line 35

def statement
  @statement
end

Class Method Details

.build(r_interop) ⇒ Object



Parameters:

  • r_interop (Interop)

    pointer to an R object

Returns:

  • the R object wrapped in a Ruby class



74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
# File 'lib/R_interface/robject.rb', line 74

def self.build(r_interop)

  # if the value is actually not an r_interop, then just return it: native Ruby
  # object
  if (!Truffle::Interop.foreign?(r_interop))
    # puts "I'm native"
    return r_interop
  # a matrix is also a vector... test should come before
  elsif (R::Support.eval("is.matrix").call(r_interop) == true)
    # puts "1"
    R::Matrix.new(r_interop)
  elsif (R::Support.eval("is.atomic").call(r_interop) == true)
    # puts "2"
    Vector.new(r_interop)
  elsif (R::Support.eval("is.function").call(r_interop) == true)
    # puts "3"
    Closure.new(r_interop)
  elsif (R::Support.eval("is.data.frame").call(r_interop) == true)
    # puts "4"
    DataFrame.new(r_interop)
  elsif (R::Support.eval("is.list").call(r_interop) == true)
    # puts "5"
    List.new(r_interop)
  elsif (R::Support.eval("typeof").call(r_interop) == "language")
    # @TODO: tests are passing both when we use Language.new
    # and RExpression.new.  Check what should be and write
    # discriminating tests.
    # print "robject buid: language\n"
    # R::Support.print_foreign(r_interop)
    # puts "6"
    Language.new(r_interop)
    # RExpression.new(r_interop)
  elsif (R::Support.eval("typeof").call(r_interop) == "expression")
    # puts "7"
    RExpression.new(r_interop)
  elsif (R::Support.eval("typeof").call(r_interop) == "name")
    # puts "8"
    p "i'm of type name"
    Name.new(r_interop)
  elsif (R::Support.eval("typeof").call(r_interop) == "symbol")
    # puts "9"
    RSymbol.new(r_interop)
  elsif (R::Support.eval("typeof").call(r_interop) == "environment")
    # puts "10"
    Environment.new(r_interop)
  else # Generic type
    # puts "11"
    p "Generic type: #{R::Support.eval("typeof").call(r_interop).to_s}"
    r_interop
  end

end

Instance Method Details

#==(other_object) ⇒ Object


Checks for equality between two R::Objects. This method is used by rspec’s expectation. It returns a Ruby true or false and not an R::Vector with [TRUE] or

FALSE



51
52
53
54
55
56
57
# File 'lib/R_interface/robject.rb', line 51

def ==(other_object)
  res =
    R::Support.exec_function_name('identical', @r_interop,
                                  R::Support.parse_arg(other_object))
  return nil if (res.length >> 0) == 0
  res >> 0
end

#_(*args) ⇒ Object


We use the following notation to access binary R functions such as %in%: R.vec_ “in”, list. arguments are the list of arguments for the function.


Parameters:

  • args (Array)

    The first element of the array is an R infix function, the other



182
183
184
185
186
# File 'lib/R_interface/robject.rb', line 182

def _(*args)
  name = "`%#{args.shift.to_s}%`"
  args.unshift(@r_interop)
  R::Support.exec_function_name(name, *args)
end

#attr=(which: w, value: v) ⇒ Object





305
306
307
308
309
# File 'lib/R_interface/robject.rb', line 305

def attr=(which: w, value: v)
  value = (R::Support.interop(value) ? value.r_interop : value)
  # setR(@@set_attr, which, value)
  setR_name("`attr<-`", which, value)
end

#commentObject



246
247
248
# File 'lib/R_interface/robject.rb', line 246

def comment
  R::Support.exec_function_name("comment", @r_interop)
end

#comment=(comment_text) ⇒ Object





242
243
244
# File 'lib/R_interface/robject.rb', line 242

def comment=(comment_text)
  setR_name("`comment<-`", comment_text)
end

#dimObject



258
259
260
# File 'lib/R_interface/robject.rb', line 258

def dim
  R::Support.exec_function_name("dim", @r_interop)
end

#dim=(numeric_vector) ⇒ Object





254
255
256
# File 'lib/R_interface/robject.rb', line 254

def dim=(numeric_vector)
  setR_name("`dim<-`", numeric_vector)
end

#dimnamesObject



270
271
272
# File 'lib/R_interface/robject.rb', line 270

def dimnames
  R::Support.exec_function_name("dimnames", @r_interop)
end

#dimnames=(names_vector) ⇒ Object





266
267
268
# File 'lib/R_interface/robject.rb', line 266

def dimnames=(names_vector)
  setR_name("`dimnames<-`", names_vector)
end

#eql(other_object) ⇒ Object


Use eql to check for equality between two objects and receive in return an R::Vector




63
64
65
66
67
# File 'lib/R_interface/robject.rb', line 63

def eql(other_object)
  # exec_bin_oper("`==`", other_object)
  R::Support.exec_function_name("`==`", @r_interop,
                                R::Support.parse_arg(other_object))
end

#names(*args) ⇒ Object



220
221
222
223
224
# File 'lib/R_interface/robject.rb', line 220

def names(*args)
  return R::Support.exec_function_name("names", @r_interop) if (args.length == 0)
  setR_name("`names<-`", *args)
  self
end

#names=(names_vector) ⇒ Object


Sets the names attribute of the object


Parameters:

  • names_vector (R::Object)

    is an RVector with the list of names.



216
217
218
# File 'lib/R_interface/robject.rb', line 216

def names=(names_vector)
  setR_name("`names<-`", names_vector)
end

#ppObject





315
316
317
# File 'lib/R_interface/robject.rb', line 315

def pp
  R.print(@r_interop)
end

#pretty_print(obj) ⇒ Object





323
324
325
# File 'lib/R_interface/robject.rb', line 323

def pretty_print(obj)
  puts self
end

#rclassObject



234
235
236
# File 'lib/R_interface/robject.rb', line 234

def rclass
  R::Support.exec_function_name("class", @r_interop)
end

#rclass=(class_name) ⇒ Object





230
231
232
# File 'lib/R_interface/robject.rb', line 230

def rclass=(class_name)
  setR_name("`class<-`", class_name)
end

#row__namesObject



285
286
287
# File 'lib/R_interface/robject.rb', line 285

def row__names
  R::Support.exec_function_name("row.names", @r_interop)
end

#row__names=(names_vector) ⇒ Object

since we need to call a method and the method changes the object, then we need to change our internal pointer also @r_interop. Ideally, just setting the row.names should work.



281
282
283
# File 'lib/R_interface/robject.rb', line 281

def row__names=(names_vector)
  setR_name("`row.names<-`", names_vector)
end

#setR(method, *args) ⇒ Object


Sets the current object self interop pointer to the returned value of the execution of the given method with arguments. This method should be called when R will copy the parameter, but in Ruby we want to hide the copying.


Parameters:

  • Interop (Interop)

    pointer to R function

  • Array (Array)

    of arguments



196
197
198
199
# File 'lib/R_interface/robject.rb', line 196

def setR(method, *args)
  @r_interop = R::Support.exec_function_i(method, @r_interop, *args)
  self
end

#setR_name(method_name, *args) ⇒ Object





205
206
207
208
209
# File 'lib/R_interface/robject.rb', line 205

def setR_name(method_name, *args)
  method = R::Support.eval(method_name)
  setR(method, *args)
  self
end

#to_sObject





331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
# File 'lib/R_interface/robject.rb', line 331

def to_s

  begin
    cap = nil
    cap = R::Support.capture2.call(r_interop)
    str = String.new
    (0...(cap.size - 1)).each do |i|
      str << cap[i] << "\n"
    end
    str << cap[cap.size - 1] if cap.size >= 1
    str
  rescue StandardError => e
    puts e
  end
  
end

#tspObject



297
298
299
# File 'lib/R_interface/robject.rb', line 297

def tsp
  R::Support.exec_function_name("tsp", @r_interop)
end

#tsp=(numeric_vector) ⇒ Object





293
294
295
# File 'lib/R_interface/robject.rb', line 293

def tsp=(numeric_vector)
  setR_name("`tsp<-`", numeric_vector)
end