r_bridge 0.5.1 → 0.5.2

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: ee29073e5090bf0ac44de5a81374aad07050f0518ea7bd0c3942d4d7ce523487
4
+ data.tar.gz: b93811a27fb58066cd93660009c0a9555cf7e74380727149e9f8a353ccb8893d
5
5
  SHA512:
6
- metadata.gz: 2eabdfe3403067cd795090593deeb96ba2a7d70ace07e9e7540d598df234134bf5969143fcdc27695a09bf65692c24e6fb78db3f59a91b3ce8d741f43382b5c1
7
- data.tar.gz: eb0e3cd227b22842584c686b9c93af7ca36434d2754132f58544fcc72b69b406630639abf2a021f2c2c160ecd3c6451d4c842517b806299198aaa5bf48a73a13
6
+ metadata.gz: ce3cbb9fd43d040599d88e3f49512917b9981f268816c5f82ae2e0722d86e33e3934ae5dacf796e0c467bdd6ff08001b33f2c25cb97d594698adbe895a199344
7
+ data.tar.gz: b850ea4e23d9a5b504c94ca761640a9e3e8f34bb08b79809b6e563d0457ac9b9f31257b1817e3eb4c47cb66ec8862c2acbc928ced2a0c901bb445cad656b613b
data/README.md CHANGED
@@ -216,11 +216,13 @@ 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
220
 
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.
221
+ Arguments are passed 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
222
 
223
223
  ```
224
+ RBridge.create_ns_function_call( ns, fname, hash )
225
+ RBridge.create_env_function_call( env, fname, hash )
224
226
  RBridge.create_function_call( fname, hash )
225
227
 
226
228
  (e.g.)
@@ -231,6 +233,21 @@ RBridge.exec_function_no_return(hellowrold)
231
233
  # pass another function call to argument
232
234
  getwd = RBridge.create_function_call( "print", { "x" => RBridge.create_function_call( "getwd", {} ) } )
233
235
  RBridge.exec_function_no_return(getwd)
236
+
237
+ # call sqrt function in base package.
238
+ ivec = RBridge.create_intvec([1,2,3])
239
+ calc = RBridge.create_ns_function_call( "base","sqrt", {"x" => ivec} )
240
+ RBridge.exec_function_no_return( RBridge.create_function_call( "print", {"" => calc} )) # execute & print out
241
+
242
+ # Call function in environment
243
+ #
244
+ # (e.g.) source the following newenv.R and call the newenv$hello function.
245
+ # # newenv.R
246
+ # newenv = new.env()
247
+ # newenv$hello = function(){ print("Hello!") }
248
+ #
249
+ RBridge.exec_function_no_return( RBridge.create_function_call("source", { "" => RBridge.create_strvec(["newenv.R"]) }))
250
+ RBridge.exec_function_no_return( RBridge.create_env_function_call("newenv", "hello", { } ))
234
251
  ```
235
252
 
236
253
  The followings are utility functions. assign() and library() are frequently used in R, and easy ways to create them are provided.
@@ -356,7 +373,7 @@ RBridge.end_embedded_r()
356
373
 
357
374
  ## Additional Features
358
375
 
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.
376
+ * 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
377
 
361
378
  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
379
 
@@ -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
  {
@@ -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
@@ -272,6 +274,10 @@ module RBridge
272
274
  return new_lcons
273
275
  end
274
276
 
277
+ def self.r_nil()
278
+ return r_lang_nil()
279
+ end
280
+
275
281
  def self.is_r_nil?( obj )
276
282
  result = r_is_nil( obj )
277
283
  if(result == 1)
@@ -294,9 +300,8 @@ module RBridge
294
300
  return extptr
295
301
  end
296
302
 
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)
303
+ def self.hash_to_lcons_args( hash )
304
+ raise "hash_to_lcons_args should take Hash argument" if(hash.class != Hash)
300
305
  if(hash.size == 0)
301
306
  lcons_args = r_lang_nil()
302
307
  elsif(hash.size == 1)
@@ -322,6 +327,36 @@ module RBridge
322
327
  idx = idx + 1
323
328
  }
324
329
  end
330
+ return lcons_args
331
+ end
332
+
333
+ def self.create_ns_function_call( ns, fname, hash )
334
+ raise "create_ns_function_call should take String for namespace" if(ns.class != String)
335
+ raise "create_ns_function_call should take String for function name" if(fname.class != String)
336
+ raise "create_ns_function_call should take Hash for function arguments" if(hash.class != Hash)
337
+ lcons_args = hash_to_lcons_args( hash )
338
+
339
+ new_function_call = r_lang_create_ns_fcall(ns, fname, lcons_args)
340
+ ptr_manager_add_ptr_to_current( new_function_call )
341
+ return new_function_call
342
+ end
343
+
344
+ def self.create_env_function_call( env, fname, hash )
345
+ raise "create_env_function_call should take String for env" if(env.class != String)
346
+ raise "create_env_function_call should take String for function name" if(fname.class != String)
347
+ raise "create_env_function_call should take Hash for function arguments" if(hash.class != Hash)
348
+ lcons_args = hash_to_lcons_args( hash )
349
+
350
+ new_function_call = r_lang_create_env_fcall(env, fname, lcons_args)
351
+ ptr_manager_add_ptr_to_current( new_function_call )
352
+ return new_function_call
353
+ end
354
+
355
+ def self.create_function_call( fname, hash )
356
+ raise "create_function_call should take String for function name" if(fname.class != String)
357
+ raise "create_function_call should take Hash for function arguments" if(hash.class != Hash)
358
+ lcons_args = hash_to_lcons_args( hash )
359
+
325
360
  new_function_call = r_lang_create_fcall(fname, lcons_args)
326
361
  ptr_manager_add_ptr_to_current( new_function_call )
327
362
  return new_function_call
@@ -1,21 +1,46 @@
1
1
  require "r_bridge/r_bridge_ffi"
2
2
 
3
3
  module RBridge
4
+ def self.create_ns_lazy_function( ns, fname, hash , 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 for function arguments" if(hash.class != Hash)
8
+ return LazyFunc.new( ns, nil, fname, hash , param_manager)
9
+ end
10
+
11
+ def self.create_env_lazy_function( env, fname, hash , 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 for function arguments" if(hash.class != Hash)
15
+ return LazyFunc.new( nil, env, fname, hash , param_manager)
16
+ end
17
+
4
18
  def self.create_lazy_function( fname, hash , param_manager)
5
19
  raise "create_lazy_function should take String for function name" if(fname.class != String)
6
20
  raise "create_lazy_function should take Hash for function arguments" if(hash.class != Hash)
7
- return LazyFunc.new( fname, hash , param_manager)
21
+ return LazyFunc.new( nil, nil, fname, hash , param_manager)
8
22
  end
9
23
 
10
- def self.create_function_call_from_lazy_function( fname, fargs, param_manager, result_manager)
24
+ def self.create_function_call_from_lazy_function_attrs( ns, env, fname, fargs, param_manager, result_manager)
11
25
  farg_keys = fargs.keys
12
26
 
13
27
  new_arg_hash = {}
14
28
  farg_keys.each(){|key|
15
29
  val = fargs[key]
30
+
31
+ if val.is_a? RResultPrevious
32
+ 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.
33
+ if ! RBridge::is_r_nil?(r_previous) # When previous result exists
34
+ new_arg_hash[key] = r_previous
35
+ break
36
+ else # When previous result does not exist
37
+ val = val.default
38
+ end
39
+ end
40
+
16
41
  case val
17
42
  when LazyFunc then
18
- new_arg_hash[key] = create_function_call_from_lazy_function( val.fname, val.args , param_manager, result_manager )
43
+ new_arg_hash[key] = create_function_call_from_lazy_function_attrs( val.ns, val.env, val.fname, val.args , param_manager, result_manager )
19
44
  when RResultName , RResultNameArray then
20
45
  new_arg_hash[key] = result_manager.get_last_for( val )
21
46
  when RParamName then
@@ -27,13 +52,13 @@ module RBridge
27
52
  case elem
28
53
  when RResultName, RResultNameArray then
29
54
  result = result_manager.get_last_for( elem )
30
- if( ! result.nil? )
55
+ if( ! RBridge::is_r_nil?(result) )
31
56
  new_arg_hash[key] = result
32
57
  break
33
58
  end
34
59
  when RParamName then
35
60
  result = param_manager.get_r_object( elem )
36
- if( ! result.nil? )
61
+ if( ! RBridge::is_r_nil?(result) )
37
62
  new_arg_hash[key] = result
38
63
  break
39
64
  end
@@ -44,34 +69,52 @@ module RBridge
44
69
  idx = idx + 1
45
70
  end
46
71
  if(idx == val.elems.size ) # Not found
47
- new_arg_hash[key] = nil
72
+ new_arg_hash[key] = RBridge::r_nil()
48
73
  end
49
74
  else # R object
50
75
  new_arg_hash[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_hash )
81
+ else
82
+ return create_env_function_call( env, fname, new_arg_hash )
83
+ end
84
+ else
85
+ if( env.nil? )
86
+ return create_ns_function_call( ns, fname, new_arg_hash )
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,18 @@ 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
+
115
171
  class RResultManager
116
172
  def initialize
117
173
  @results = []
@@ -125,7 +181,7 @@ module RBridge
125
181
  @results << [inst_name, r_obj ]
126
182
  end
127
183
 
128
- def get_last_index_for( result_name )
184
+ def get_last_index_for( result_name ) # From this method, if result name is not found return (Ruby) nil.
129
185
  name = result_name.name
130
186
 
131
187
  idx = @results.size - 1
@@ -143,18 +199,18 @@ module RBridge
143
199
  end
144
200
  end
145
201
 
146
- def get_last_for( r_result ) # If corresponding result name is not found, return nil.
202
+ def get_last_for( r_result ) # If corresponding result name is not found, return r_nil().
147
203
  raise "get_last_for method requires RResultName or RResultNameArray for its argument." if ! ( r_result.is_a?(RResultName) || r_result.is_a?(RResultNameArray) )
148
204
  if( r_result.is_a? RResultName)
149
205
  inst_name = r_result.name
150
206
 
151
207
  elem_to_match = @results.reverse.find{|elem| elem[0] == inst_name }
152
208
  if elem_to_match.nil?
153
- return nil
209
+ return RBridge::r_nil()
154
210
  else
155
211
  r_obj = elem_to_match[1]
156
212
  if RBridge::is_r_nil?( r_obj )
157
- return nil
213
+ return RBridge::r_nil()
158
214
  else
159
215
  return r_obj
160
216
  end
@@ -170,7 +226,7 @@ module RBridge
170
226
  }
171
227
 
172
228
  if( index_array.all?(nil) )
173
- return nil
229
+ return RBridge::r_nil()
174
230
  else
175
231
  index_array.delete(nil)
176
232
  if ! index_array.empty?
@@ -178,13 +234,23 @@ module RBridge
178
234
  r_obj = @results[last_idx][1]
179
235
  return r_obj
180
236
  else
181
- return nil
237
+ return RBridge::r_nil()
182
238
  end
183
239
  end
184
240
  else
185
241
  raise "get_last_for() takes unexpected object"
186
242
  end
187
243
  end
244
+
245
+ def get_previous()
246
+ p @results
247
+ if @results.size > 0
248
+ r_obj = @results.last[1]
249
+ return r_obj
250
+ else
251
+ return RBridge::r_nil()
252
+ end
253
+ end
188
254
  end
189
255
 
190
256
  class RNameContainer
@@ -1,3 +1,3 @@
1
1
  module RBridge
2
- VERSION = "0.5.1"
2
+ VERSION = "0.5.2"
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.2
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-01-31 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
@@ -89,7 +89,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
89
89
  version: '0'
90
90
  requirements: []
91
91
  rubygems_version: 3.1.2
92
- signing_key:
92
+ signing_key:
93
93
  specification_version: 4
94
94
  summary: Enables Ruby to construct and evaluate R internal objects
95
95
  test_files: []