r_bridge 0.5.1 → 0.5.5

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 678aaf66ad022546771461a682f5dee6efa065402c8890197ac3e809cb491cda
4
- data.tar.gz: 6e4c24a1f8fc85599707ca0aa7799a8b7ef7bfbb0fcb7e1f1cc720f58f179046
3
+ metadata.gz: ad1d735bada2b3edde78582804db6ed1c260663f59fb52e236adf678248b75d7
4
+ data.tar.gz: 619abe8dc2e78aa7fae3d20c68da7279a67b72a4fe934562e6ef8d613cadb14b
5
5
  SHA512:
6
- metadata.gz: 2eabdfe3403067cd795090593deeb96ba2a7d70ace07e9e7540d598df234134bf5969143fcdc27695a09bf65692c24e6fb78db3f59a91b3ce8d741f43382b5c1
7
- data.tar.gz: eb0e3cd227b22842584c686b9c93af7ca36434d2754132f58544fcc72b69b406630639abf2a021f2c2c160ecd3c6451d4c842517b806299198aaa5bf48a73a13
6
+ metadata.gz: da62f2782de29b146aa36909f9ddf40d4135379535a5a885abb6a1e50a981218d066d9f0dc444f8e7a678f1cac85375ba3385ace6bbc48be5ad37ef5c9fc29f5
7
+ data.tar.gz: c05bc29469b5b61629ef4e0575efae12f99a665fdba8df9f23d4f8106de83aa52b3b2fc124c741de525ab9e234c4b599dded80597ebe9824ddd7f2786dd606c6
data/README.md CHANGED
@@ -216,12 +216,17 @@ RBridge.create_extptr( ffi_ptr )
216
216
 
217
217
  * Create R function call
218
218
 
219
- create_function_call creates R's internal S expresion structure for function call.
219
+ create_ns_function_call, create_env_function_call and create_function_call create R's internal S expresion structures for function calls. create_ns_function_call can specify (package) namespace. create_env_function_call can specify environment name.
220
+
221
+ Arguments are passed as Ruby's Hash like objects, Hash or assocation Array, and their each element's value needs to be R's object. For these R objects You can assign not only R vectors but also other function calls.
222
+
223
+ Assocation Arrays are useful when you have more than one elements with the same key name, which Hash does not allow. This happens when you do not specify parameter name and you use empty Strings, "", as parameter names.
220
224
 
221
- Arguments are passed to the second argument as Ruby Hash, and each Hash's value needs to point to R's object. You usually pass R vectors, but you can also pass another function call as an argument.
222
225
 
223
226
  ```
224
- RBridge.create_function_call( fname, hash )
227
+ RBridge.create_ns_function_call( ns, fname, hash_like )
228
+ RBridge.create_env_function_call( env, fname, hash_like )
229
+ RBridge.create_function_call( fname, hash_like )
225
230
 
226
231
  (e.g.)
227
232
  # pass vector to argument
@@ -231,6 +236,25 @@ RBridge.exec_function_no_return(hellowrold)
231
236
  # pass another function call to argument
232
237
  getwd = RBridge.create_function_call( "print", { "x" => RBridge.create_function_call( "getwd", {} ) } )
233
238
  RBridge.exec_function_no_return(getwd)
239
+
240
+ # call sqrt function in base package.
241
+ ivec = RBridge.create_intvec([1,2,3])
242
+ calc = RBridge.create_ns_function_call( "base","sqrt", {"x" => ivec} )
243
+ RBridge.exec_function_no_return( RBridge.create_function_call( "print", {"" => calc} )) # execute & print out
244
+
245
+ # Call function in environment
246
+ #
247
+ # (e.g.) source the following newenv.R and call the newenv$hello function.
248
+ # # newenv.R
249
+ # newenv = new.env()
250
+ # newenv$hello = function(){ print("Hello!") }
251
+ #
252
+ RBridge.exec_function_no_return( RBridge.create_function_call("source", { "" => RBridge.create_strvec(["newenv.R"]) }))
253
+ RBridge.exec_function_no_return( RBridge.create_env_function_call("newenv", "hello", { } ))
254
+
255
+ # pass association Array to argument
256
+ add = RBridge.create_function_call( "+", [["" , RBridge.create_intvec( [1,2,3] )],["", RBridge.create_intvec( [10,20,30] ) ]] )
257
+ RBridge.exec_function( RBridge.create_function_call("print", [["" , add ]]))
234
258
  ```
235
259
 
236
260
  The followings are utility functions. assign() and library() are frequently used in R, and easy ways to create them are provided.
@@ -356,7 +380,7 @@ RBridge.end_embedded_r()
356
380
 
357
381
  ## Additional Features
358
382
 
359
- * LazyFunc + RParamManager (+ RResultManager): In contrast to create_function_call(), create_lazy_funcion(), which create LazyFunc object, does not need to take existent R objects. It can take RParamName, RResultName and so on, which are not associated with R objects until the function is evaluated.
383
+ * LazyFunc + RParamManager (+ RResultManager): In contrast to create_function_call(), create_lazy_function(), which creates LazyFunc object, does not need to take existent R objects. It can take RParamName, RResultName and so on, which are not associated with R objects until the function is evaluated. create_ns_lazy_function(), create_env_lazy_function() are lazy evaluation version of create_ns_function_call() and create_env_function_call(), which respectively allows specifying namespaces and environments.
360
384
 
361
385
  These features are being developed for StatSailr, and the API is not stable. They can be accessed but they are not recommended for general usage.
362
386
 
@@ -2,25 +2,55 @@
2
2
  #include <Rembedded.h>
3
3
  #include <Rdefines.h>
4
4
 
5
+ #include <stdbool.h>
6
+
7
+ #include <stdint.h>
8
+ #define CSTACK_DEFNS
9
+ #include <Rinterface.h>
10
+
5
11
  #include "win_compat.h"
6
12
 
13
+ #ifdef __FreeBSD__
14
+ #include <ieeefp.h>
15
+ fp_rnd_t fpmask_preset;
16
+ #endif
17
+
7
18
  EXPORT void
8
- r_embedded_init()
19
+ r_embedded_init( bool unlimited_stack_size )
9
20
  {
10
- size_t localArgc = 2;
11
- char localArgs[][50] = {"R", "--silent"};
21
+
22
+ #ifdef __FreeBSD__
23
+ fpmask_preset = fpsetmask(0);
24
+ #endif
25
+
26
+ size_t localArgc = 3;
27
+ char localArgs[][50] = {"R", "--silent", "--vanilla"};
12
28
 
13
29
  char *args[ localArgc ];
14
30
  for (size_t i = 0; i < localArgc; ++i){
15
31
  args[i] = localArgs[i];
16
32
  }
17
33
 
18
- Rf_initEmbeddedR( localArgc , args );
34
+ // Rf_initEmbeddedR raises C stack usage limit error on multithreading environment.
35
+ // Rf_initEmbeddedR( localArgc , args ); is replaced with the following code.
36
+
37
+ if( unlimited_stack_size == false ){ // default stack size
38
+ Rf_initialize_R( localArgc , args );
39
+ setup_Rmainloop();
40
+ }else{
41
+ Rf_initialize_R( localArgc , args );
42
+ R_CStackLimit = (uintptr_t) -1 ; // Set -1 for unlimited C stack size.
43
+ setup_Rmainloop();
44
+ }
19
45
  }
20
46
 
21
47
  EXPORT void
22
48
  r_embedded_end()
23
49
  {
24
50
  Rf_endEmbeddedR(0);
51
+
52
+ #ifdef __FreeBSD__
53
+ fpsetmask(fpmask_preset);
54
+ #endif
25
55
  }
26
56
 
@@ -4,6 +4,22 @@
4
4
 
5
5
  #include "win_compat.h"
6
6
 
7
+ EXPORT SEXP
8
+ r_lang_create_ns_fcall( const char* ns, const char* fname, SEXP args)
9
+ {
10
+ SEXP func;
11
+ PROTECT( func = LCONS( LCONS( Rf_install("::"), LCONS( Rf_install(ns), LCONS( Rf_install(fname), R_NilValue))) , args ));
12
+ return func;
13
+ }
14
+
15
+ EXPORT SEXP
16
+ r_lang_create_env_fcall( const char* env, const char* fname, SEXP args)
17
+ {
18
+ SEXP func;
19
+ PROTECT( func = LCONS( LCONS( Rf_install("$"), LCONS( Rf_install(env), LCONS( Rf_install(fname), R_NilValue))) , args ));
20
+ return func;
21
+ }
22
+
7
23
  EXPORT SEXP
8
24
  r_lang_create_fcall( const char* fname, SEXP args)
9
25
  {
@@ -12,7 +28,6 @@ r_lang_create_fcall( const char* fname, SEXP args)
12
28
  return func;
13
29
  }
14
30
 
15
-
16
31
  EXPORT SEXP
17
32
  r_lang_cons( SEXP car, SEXP cdr)
18
33
  {
@@ -7,7 +7,7 @@ module RBridge
7
7
  lib_name = "librbridge" + "." + RbConfig::CONFIG['DLEXT']
8
8
  ffi_lib File.expand_path( lib_name, __dir__ )
9
9
 
10
- attach_function :r_embedded_init, [], :void
10
+ attach_function :r_embedded_init, [:bool], :void
11
11
  attach_function :r_embedded_end, [], :void
12
12
 
13
13
  attach_function :r_vec_create_str, [:int], :pointer
@@ -24,6 +24,8 @@ module RBridge
24
24
  attach_function :r_list_to_dataframe, [:pointer ], :pointer
25
25
  attach_function :r_dataframe_set_rownames, [:pointer, :pointer], :void
26
26
 
27
+ attach_function :r_lang_create_ns_fcall, [:string, :string, :pointer], :pointer
28
+ attach_function :r_lang_create_env_fcall, [:string, :string, :pointer], :pointer
27
29
  attach_function :r_lang_create_fcall, [:string, :pointer], :pointer
28
30
  attach_function :r_lang_cons, [:pointer, :pointer], :pointer
29
31
  attach_function :r_lang_cons_gen, [:pointer], :pointer
@@ -47,8 +49,11 @@ module RBridge
47
49
 
48
50
  # From here, Ruby interface
49
51
 
50
- def self.init_embedded_r()
51
- r_embedded_init()
52
+ def self.init_embedded_r( unlimited_cstack: false )
53
+ if(unlimited_cstack.class != TrueClass && unlimited_cstack.class != FalseClass)
54
+ raise "init_embedded_r() can take true or false for unlimited C stack size. true: unlimited, false: default."
55
+ end
56
+ r_embedded_init( unlimited_cstack )
52
57
  end
53
58
 
54
59
  def self.end_embedded_r()
@@ -256,6 +261,8 @@ module RBridge
256
261
  else
257
262
  r_obj = value.to_r_symbol
258
263
  end
264
+ when value.class == NilClass
265
+ r_obj = RBridge.r_nil
259
266
  end
260
267
  return r_obj
261
268
  end
@@ -272,6 +279,10 @@ module RBridge
272
279
  return new_lcons
273
280
  end
274
281
 
282
+ def self.r_nil()
283
+ return r_lang_nil()
284
+ end
285
+
275
286
  def self.is_r_nil?( obj )
276
287
  result = r_is_nil( obj )
277
288
  if(result == 1)
@@ -294,21 +305,44 @@ module RBridge
294
305
  return extptr
295
306
  end
296
307
 
297
- def self.create_function_call( fname, hash )
298
- raise "create_function_call should take String for function name" if(fname.class != String)
299
- raise "create_function_call should take Hash for function arguments" if(hash.class != Hash)
300
- if(hash.size == 0)
308
+ def self.array_depth (ary)
309
+ return 0 unless ary.is_a?(Array)
310
+ return 1 + ary.map(){|elem| array_depth(elem) }.max()
311
+ end
312
+
313
+ def self.assoc_array?(ary)
314
+ if ary.map(){|elem| elem.size }.uniq == [2]
315
+ true
316
+ else
317
+ false
318
+ end
319
+ end
320
+
321
+ def self.hash_to_lcons_args( hash_like )
322
+ if hash_like.class == Hash
323
+ # hash
324
+ elsif hash_like.class == Array
325
+ if array_depth(hash_like) == 2 && assoc_array?(hash_like)
326
+ # association array
327
+ else
328
+ raise "hash_to_lcons_args should take Hash argument (or Association Array argument)"
329
+ end
330
+ else
331
+ raise "hash_to_lcons_args should take Hash argument (or Association Array argument)"
332
+ end
333
+
334
+ if(hash_like.size == 0)
301
335
  lcons_args = r_lang_nil()
302
- elsif(hash.size == 1)
303
- tag = hash.first[0]
304
- val = hash.first[1]
336
+ elsif(hash_like.size == 1)
337
+ tag = hash_like.first[0]
338
+ val = hash_like.first[1]
305
339
  lcons_args = lcons_gen( val )
306
340
  if( tag != "" )
307
341
  set_tag_to_lcons( lcons_args, tag )
308
342
  end
309
343
  else
310
344
  idx = 0
311
- hash.reverse_each(){|arg|
345
+ hash_like.reverse_each(){|arg|
312
346
  tag = arg[0]
313
347
  val = arg[1]
314
348
  if(idx == 0 )
@@ -322,6 +356,36 @@ module RBridge
322
356
  idx = idx + 1
323
357
  }
324
358
  end
359
+ return lcons_args
360
+ end
361
+
362
+ def self.create_ns_function_call( ns, fname, hash_like )
363
+ raise "create_ns_function_call should take String for namespace" if(ns.class != String)
364
+ raise "create_ns_function_call should take String for function name" if(fname.class != String)
365
+ raise "create_ns_function_call should take Hash like structure for function arguments" if(hash_like.class != Hash && hash_like.class != Array)
366
+ lcons_args = hash_to_lcons_args( hash_like )
367
+
368
+ new_function_call = r_lang_create_ns_fcall(ns, fname, lcons_args)
369
+ ptr_manager_add_ptr_to_current( new_function_call )
370
+ return new_function_call
371
+ end
372
+
373
+ def self.create_env_function_call( env, fname, hash_like )
374
+ raise "create_env_function_call should take String for env" if(env.class != String)
375
+ raise "create_env_function_call should take String for function name" if(fname.class != String)
376
+ raise "create_env_function_call should take Hash like structure for function arguments" if(hash_like.class != Hash && hash_like.class != Array)
377
+ lcons_args = hash_to_lcons_args( hash_like )
378
+
379
+ new_function_call = r_lang_create_env_fcall(env, fname, lcons_args)
380
+ ptr_manager_add_ptr_to_current( new_function_call )
381
+ return new_function_call
382
+ end
383
+
384
+ def self.create_function_call( fname, hash_like )
385
+ raise "create_function_call should take String for function name" if(fname.class != String)
386
+ raise "create_function_call should take Hash like structure for function arguments" if(hash_like.class != Hash && hash_like.class != Array)
387
+ lcons_args = hash_to_lcons_args( hash_like )
388
+
325
389
  new_function_call = r_lang_create_fcall(fname, lcons_args)
326
390
  ptr_manager_add_ptr_to_current( new_function_call )
327
391
  return new_function_call
@@ -1,25 +1,48 @@
1
1
  require "r_bridge/r_bridge_ffi"
2
2
 
3
3
  module RBridge
4
- def self.create_lazy_function( fname, hash , param_manager)
4
+ def self.create_ns_lazy_function( ns, fname, hash_like , param_manager)
5
+ raise "create_ns_lazy_function should take String for namespace" if(ns.class != String)
6
+ raise "create_ns_lazy_function should take String for function name" if(fname.class != String)
7
+ raise "create_ns_lazy_function should take Hash like structure for function arguments" if(hash_like.class != Hash && hash_like.class != Array)
8
+ return LazyFunc.new( ns, nil, fname, hash_like, param_manager)
9
+ end
10
+
11
+ def self.create_env_lazy_function( env, fname, hash_like , param_manager)
12
+ raise "create_env_lazy_function should take String for environment" if(env.class != String)
13
+ raise "create_env_lazy_function should take String for function name" if(fname.class != String)
14
+ raise "create_env_lazy_function should take Hash like structure for function arguments" if(hash_like.class != Hash && hash_like.class != Array)
15
+ return LazyFunc.new( nil, env, fname, hash_like, param_manager)
16
+ end
17
+
18
+ def self.create_lazy_function( fname, hash_like , param_manager)
5
19
  raise "create_lazy_function should take String for function name" if(fname.class != String)
6
- raise "create_lazy_function should take Hash for function arguments" if(hash.class != Hash)
7
- return LazyFunc.new( fname, hash , param_manager)
20
+ raise "create_lazy_function should take Hash like structure for function arguments" if(hash_like.class != Hash && hash_like.class != Array)
21
+ return LazyFunc.new( nil, nil, fname, hash_like, param_manager)
8
22
  end
9
23
 
10
- def self.create_function_call_from_lazy_function( fname, fargs, param_manager, result_manager)
11
- farg_keys = fargs.keys
24
+ def self.create_function_call_from_lazy_function_attrs( ns, env, fname, fargs, param_manager, result_manager)
25
+
26
+ new_arg_assoc_array = []
27
+ fargs.each(){|key, val|
28
+
29
+ if val.is_a? RResultPrevious
30
+ r_previous = result_manager.get_previous() # if r_nil (i.e. 1st instruction or no previous result-store instructions) we need to use default one.
31
+ if ! RBridge::is_r_nil?(r_previous) # When previous result exists
32
+ new_arg_assoc_array << [key, r_previous]
33
+ next
34
+ else # When previous result does not exist
35
+ val = val.default
36
+ end
37
+ end
12
38
 
13
- new_arg_hash = {}
14
- farg_keys.each(){|key|
15
- val = fargs[key]
16
39
  case val
17
40
  when LazyFunc then
18
- new_arg_hash[key] = create_function_call_from_lazy_function( val.fname, val.args , param_manager, result_manager )
41
+ new_arg_assoc_array << [key, create_function_call_from_lazy_function_attrs( val.ns, val.env, val.fname, val.args , param_manager, result_manager )]
19
42
  when RResultName , RResultNameArray then
20
- new_arg_hash[key] = result_manager.get_last_for( val )
43
+ new_arg_assoc_array << [key, result_manager.get_last_for( val )]
21
44
  when RParamName then
22
- new_arg_hash[key] = param_manager.get_r_object( val )
45
+ new_arg_assoc_array << [key, param_manager.get_r_object( val )]
23
46
  when RNameContainer then
24
47
  idx = 0
25
48
  while idx < val.elems.size do
@@ -27,51 +50,71 @@ module RBridge
27
50
  case elem
28
51
  when RResultName, RResultNameArray then
29
52
  result = result_manager.get_last_for( elem )
30
- if( ! result.nil? )
31
- new_arg_hash[key] = result
53
+ if( ! RBridge::is_r_nil?(result) )
54
+ new_arg_assoc_array << [key, result]
32
55
  break
33
56
  end
34
57
  when RParamName then
35
58
  result = param_manager.get_r_object( elem )
36
- if( ! result.nil? )
37
- new_arg_hash[key] = result
59
+ if( ! RBridge::is_r_nil?(result) )
60
+ new_arg_assoc_array << [key, result]
38
61
  break
39
62
  end
40
63
  else # R object
41
- new_arg_hash[key] = val
64
+ new_arg_assoc_array << [key, val]
42
65
  break
43
66
  end
44
67
  idx = idx + 1
45
68
  end
46
69
  if(idx == val.elems.size ) # Not found
47
- new_arg_hash[key] = nil
70
+ new_arg_assoc_array << [key, RBridge::r_nil()]
48
71
  end
72
+ when RInstPrevious
73
+ new_arg_assoc_array << [key, result_manager.get_previous_inst_name() ]
49
74
  else # R object
50
- new_arg_hash[key] = val
75
+ new_arg_assoc_array << [key, val]
51
76
  end
52
77
  }
53
- return create_function_call( fname, new_arg_hash )
78
+ if( ns.nil? )
79
+ if( env.nil? )
80
+ return create_function_call( fname, new_arg_assoc_array )
81
+ else
82
+ return create_env_function_call( env, fname, new_arg_assoc_array )
83
+ end
84
+ else
85
+ if( env.nil? )
86
+ return create_ns_function_call( ns, fname, new_arg_assoc_array )
87
+ else
88
+ raise "namespace and environment are not allowed to be specified at the same time."
89
+ end
90
+ end
54
91
  end
55
92
 
56
93
  def self.exec_lazy_function( lazy_func , result_manager , allow_nil_result: false )
57
94
  raise "exec_lazy_function should take LazyFunc object" if(lazy_func.class != LazyFunc)
58
95
  raise "exec_lazy_function should take RResultManager or Nil for 2nd argment: " + result_manager.class.to_s if(! [RResultManager, NilClass].include?(result_manager.class) )
96
+ ns = lazy_func.ns
97
+ env = lazy_func.env
59
98
  fname = lazy_func.fname
60
99
  arg_hash = lazy_func.args
61
100
  param_manager = lazy_func.param_manager
62
101
 
63
- func = create_function_call_from_lazy_function(fname, arg_hash, param_manager, result_manager)
102
+ func = create_function_call_from_lazy_function_attrs(ns, env, fname, arg_hash, param_manager, result_manager)
64
103
  result = exec_function( func , allow_nil_result: allow_nil_result )
65
104
  return result
66
105
  end
67
106
 
68
107
  class LazyFunc
108
+ attr :ns
109
+ attr :env
69
110
  attr :fname
70
111
  attr :args
71
112
  attr :param_manager
72
113
 
73
- def initialize( fname, arg_hash, param_manager)
114
+ def initialize( ns, env, fname, arg_hash, param_manager)
74
115
  raise "LazyFunc requires RParamManager object for param_manager argument " if ! param_manager.is_a?(RParamManager)
116
+ @ns = ns # When namespace does not need to be specified, set nil.
117
+ @env = env # When environment does not need to be specified, set nil.
75
118
  @fname = fname
76
119
  @args = arg_hash
77
120
  @param_manager = param_manager
@@ -86,6 +129,7 @@ module RBridge
86
129
  end
87
130
 
88
131
  class RParamManager
132
+ attr :param_hash , true
89
133
  def initialize(hash)
90
134
  @param_hash = hash
91
135
  end
@@ -112,6 +156,22 @@ module RBridge
112
156
  end
113
157
  end
114
158
 
159
+ class RResultPrevious
160
+ # RResultPrevious is used for result from the previous instruction.
161
+ # If the instruction is the 1st one, there are no previous ones. At this time, default one is used.
162
+ attr :default
163
+ def initialize(val)
164
+ if ! ( val.is_a?(RNameContainer) || val.is_a?(RResultName) || val.is_a?(RResultNameArray) || val.is_a?(RParamName) || ::RBridge.is_pointer?( val ) )
165
+ raise "RResultPrevious.new requires RNameContainer, RResultName, RResultNameArray, RParamName or R object as default"
166
+ end
167
+ @default = val
168
+ end
169
+ end
170
+
171
+ class RInstPrevious
172
+ # RInstPrevious is used to obtain the previous instruction name.
173
+ end
174
+
115
175
  class RResultManager
116
176
  def initialize
117
177
  @results = []
@@ -125,7 +185,7 @@ module RBridge
125
185
  @results << [inst_name, r_obj ]
126
186
  end
127
187
 
128
- def get_last_index_for( result_name )
188
+ def get_last_index_for( result_name ) # From this method, if result name is not found return (Ruby) nil.
129
189
  name = result_name.name
130
190
 
131
191
  idx = @results.size - 1
@@ -143,18 +203,18 @@ module RBridge
143
203
  end
144
204
  end
145
205
 
146
- def get_last_for( r_result ) # If corresponding result name is not found, return nil.
206
+ def get_last_for( r_result ) # If corresponding result name is not found, return r_nil().
147
207
  raise "get_last_for method requires RResultName or RResultNameArray for its argument." if ! ( r_result.is_a?(RResultName) || r_result.is_a?(RResultNameArray) )
148
208
  if( r_result.is_a? RResultName)
149
209
  inst_name = r_result.name
150
210
 
151
211
  elem_to_match = @results.reverse.find{|elem| elem[0] == inst_name }
152
212
  if elem_to_match.nil?
153
- return nil
213
+ return RBridge::r_nil()
154
214
  else
155
215
  r_obj = elem_to_match[1]
156
216
  if RBridge::is_r_nil?( r_obj )
157
- return nil
217
+ return RBridge::r_nil()
158
218
  else
159
219
  return r_obj
160
220
  end
@@ -170,7 +230,7 @@ module RBridge
170
230
  }
171
231
 
172
232
  if( index_array.all?(nil) )
173
- return nil
233
+ return RBridge::r_nil()
174
234
  else
175
235
  index_array.delete(nil)
176
236
  if ! index_array.empty?
@@ -178,13 +238,32 @@ module RBridge
178
238
  r_obj = @results[last_idx][1]
179
239
  return r_obj
180
240
  else
181
- return nil
241
+ return RBridge::r_nil()
182
242
  end
183
243
  end
184
244
  else
185
245
  raise "get_last_for() takes unexpected object"
186
246
  end
187
247
  end
248
+
249
+ def get_previous()
250
+ if @results.size > 0
251
+ r_obj = @results.last[1]
252
+ return r_obj
253
+ else
254
+ return RBridge::r_nil()
255
+ end
256
+ end
257
+
258
+ def get_previous_inst_name()
259
+ if @results.size > 0
260
+ last_inst_name = @results.last[0]
261
+ r_obj = RBridge::create_strvec([last_inst_name])
262
+ return r_obj
263
+ else
264
+ return RBridge::r_nil()
265
+ end
266
+ end
188
267
  end
189
268
 
190
269
  class RNameContainer
@@ -1,3 +1,3 @@
1
1
  module RBridge
2
- VERSION = "0.5.1"
2
+ VERSION = "0.5.5"
3
3
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: r_bridge
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.5.1
4
+ version: 0.5.5
5
5
  platform: ruby
6
6
  authors:
7
7
  - Toshihiro Umehara
8
- autorequire:
8
+ autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2020-12-04 00:00:00.000000000 Z
11
+ date: 2021-12-05 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: ffi
@@ -73,7 +73,7 @@ metadata:
73
73
  homepage_uri: https://github.com/niceume/r_bridge
74
74
  source_code_uri: https://github.com/niceume/r_bridge
75
75
  changelog_uri: https://github.com/niceume/r_bridge
76
- post_install_message:
76
+ post_install_message:
77
77
  rdoc_options: []
78
78
  require_paths:
79
79
  - lib
@@ -88,8 +88,8 @@ required_rubygems_version: !ruby/object:Gem::Requirement
88
88
  - !ruby/object:Gem::Version
89
89
  version: '0'
90
90
  requirements: []
91
- rubygems_version: 3.1.2
92
- signing_key:
91
+ rubygems_version: 3.2.31
92
+ signing_key:
93
93
  specification_version: 4
94
94
  summary: Enables Ruby to construct and evaluate R internal objects
95
95
  test_files: []