rserve-client 0.1.6 → 0.1.7

Sign up to get free protection for your applications and to get access to all the features.
data.tar.gz.sig CHANGED
Binary file
data/Examples.txt ADDED
@@ -0,0 +1,48 @@
1
+ = Examples for Rserve
2
+
3
+ <em>Based on original Java version [http://www.rforge.net/Rserve/example.html]</em>
4
+
5
+ Rserve itself is provided as a regular R package and can be installed as such. The actual use is not performed by the library command, but by starting the Rserve executable (Windows) or typing R CMD Rserve on the command line (all others). By default Rserve runs in local mode with no enforced authentication. Once the Rserve is running any applications can use its services.
6
+
7
+ We will show examples using the Ruby client for Rserve. The principles are identical when using other Rserve clients. Before plunging into real examples, let us consider the minimal ``hello world'' example:
8
+
9
+ require 'rserve'
10
+ include Rserve
11
+ c = Connection.new
12
+ x = c.eval("R.version.string");
13
+ puts x.as_string
14
+
15
+ The code has the same effect as typing R.version.string in R. In the first line a connection to the local Rserve is established. Then the R command is evaluated and the result stored in a special object of the class REXP. This class encapsulates any objects received or sent to Rserve. If the type of the returned objects is known in advance, accessor methods can be called to obtain the Ruby object corresponding to the R value, in our case a regular String. Finally this string is printed on the standard output.
16
+
17
+ The following code fragment illustrates the use of slightly more complex native Ruby types:
18
+
19
+ d = c.eval("rnorm(100)").as_doubles
20
+
21
+
22
+ The single line in Ruby provides an array of 100 doubles representing random numbers from the standard normal distribution. The numeric vector in R is automatically converted into an array of floats. In cases where no native Ruby type exists, Rserve Ruby client defines its own classes such as Rlist or Logical (Ruby's boolean type has no support for NA missing values, therefore it cannot be used to directly represent logical type in R). This approach makes the use of Rserve very easy. As a first more practical example we want to calculate a Lowess smoother through a given set of points. The Ruby application lets the user specify the data allowing interactive changes of the points, displays a regular scatter plot and needs coordinates of the smoother to be obtained from R. One way of obtaining such a result would be to construct a long string command of the form lowes(c(0.2,0.4,...), c(2.5,4.8,...)) and using the eval method to obtain the result. This is somewhat clumsy, because the points usually already exist in an array in the Ruby application and the command string must be constructed from these. An alternative involves constructing objects in R directly. The following code shows the full Lowess example:
23
+
24
+ require 'rserve'
25
+
26
+ data_x=Rserve::REXP::Wrapper.wrap(10.times.map{|i| rand(i)})
27
+ data_y=Rserve::REXP::Wrapper.wrap(10.times.map{|i| rand(i)})
28
+ c = Rserve::Connection.new();
29
+ c.assign("x", data_x);
30
+ c.assign("y", data_y);
31
+ l = c.eval("lowess(x,y)").as_list
32
+ lx = l.at("x").as_floats
33
+ ly = l.at("y").as_floats
34
+
35
+ First the Ruby application defines the arrays for the data points data_x and data_y. The application is responsible for filling these arrays with the desired content (in this case, random data). Then we assign the contents of these arrays to R variables x and y. The assign command transfers the contents in binary form to Rserve and assigns this content to the specified symbol. This is far more efficient than constructing a string representation of the content.
36
+
37
+ Once the variables are set in R we are ready to use the lowess function. It returns a list consisting of two vectors x and y which contain the smoother points. The Rlist object provides the method at for extraction of named entries of a list. Since lists may contain entries of different types, the object returned by the at method is of the class REXP whose content can be cast into floats in our case. The result can now be used by the Ruby application.
38
+
39
+ More complex computations can be performed even without transmission of resulting objects. This is useful when defining functions or constructing complex models. Model objects are usually large, because they contain original data points, residuals and other meta data. Although they can be transferred to the client, it is more efficient to retain such objects in R and extract relevant information only. This can be done by using the void_eval method which does not transfer the result of the evaluation back to the client:
40
+
41
+ c.assign(y, ...) ...
42
+ c.void_eval("m<-lm(y~a+b+c)");
43
+ coeff = c.eval("coefficients(m)").as_floats
44
+
45
+ In the above example a linear model is fitted, but its content is not passed back to the client. It is stored in an object in R for later use. Finally the coefficients are extracted from the model and passed back to the Ruby application.
46
+
47
+ So far we used Rserve in local mode only. Extension to remote Rserve connections is possible without code changes, except for additional parameters to the Rserve::Connection constructor, specifying the remote computer running the \Rs. For details about the use of remote authentication, error handling and file transfer, consult the source code documentation.
48
+
data/History.txt CHANGED
@@ -1,3 +1,11 @@
1
+ === 0.1.7 / 2010-05-28
2
+
3
+ * Reimplement Rlist as an Array with module WithNames included
4
+ * Added modules WithAttributes and WithNames
5
+ * Added examples of use
6
+
7
+
8
+
1
9
  === 0.1.6 / 2010-05-27
2
10
  * Assign complete for all commons REXPs
3
11
  * Added Connection#shutdown
data/Manifest.txt CHANGED
@@ -1,9 +1,12 @@
1
1
  .autotest
2
2
  .gitignore
3
+ Examples.txt
3
4
  History.txt
4
5
  Manifest.txt
5
6
  README.txt
6
7
  Rakefile
8
+ examples/hello_world.rb
9
+ examples/lowless.rb
7
10
  lib/rserve.rb
8
11
  lib/rserve/connection.rb
9
12
  lib/rserve/engine.rb
@@ -32,6 +35,8 @@ lib/rserve/rexp/wrapper.rb
32
35
  lib/rserve/rfactor.rb
33
36
  lib/rserve/rlist.rb
34
37
  lib/rserve/talk.rb
38
+ lib/rserve/withattributes.rb
39
+ lib/rserve/withnames.rb
35
40
  spec/rserve_connection_spec.rb
36
41
  spec/rserve_double_spec.rb
37
42
  spec/rserve_integer_spec.rb
@@ -45,5 +50,6 @@ spec/rserve_rfactor_spec.rb
45
50
  spec/rserve_rlist_spec.rb
46
51
  spec/rserve_spec.rb
47
52
  spec/rserve_talk_spec.rb
53
+ spec/rserve_withnames_spec.rb
48
54
  spec/spec.opts
49
55
  spec/spec_helper.rb
data/Rakefile CHANGED
@@ -9,6 +9,7 @@ Hoe.spec 'rserve-client' do
9
9
  self.test_globs="spec/*_spec.rb"
10
10
  self.version=Rserve::VERSION
11
11
  self.rubyforge_name = 'ruby-statsample' # if different than 'rserve'
12
+ self.remote_rdoc_dir = "rserve-client"
12
13
  self.developer('Claudio Bustos', 'clbustos_AT_gmail.com')
13
14
  end
14
15
 
@@ -0,0 +1,8 @@
1
+ require 'rserve'
2
+ include Rserve
3
+ c = Connection.new
4
+ x = c.eval("R.version.string");
5
+ puts x.as_string
6
+
7
+
8
+ d = c.eval("rnorm(100)").as_doubles
@@ -0,0 +1,10 @@
1
+ require 'rserve'
2
+
3
+ data_x=Rserve::REXP::Wrapper.wrap(10.times.map{|i| rand(i)})
4
+ data_y=Rserve::REXP::Wrapper.wrap(10.times.map{|i| rand(i)})
5
+ c = Rserve::Connection.new();
6
+ c.assign("x", data_x);
7
+ c.assign("y", data_y);
8
+ l = c.eval("lowess(x,y)").as_list
9
+ lx = l.at("x").as_floats
10
+ ly = l.at("y").as_floats
data/lib/rserve.rb CHANGED
@@ -1,10 +1,14 @@
1
1
  require 'socket'
2
2
 
3
3
  module Rserve
4
- VERSION = '0.1.6'
4
+ VERSION = '0.1.7'
5
5
  end
6
6
 
7
7
 
8
+ require 'rserve/withnames'
9
+ require 'rserve/withattributes'
10
+
11
+
8
12
  require 'rserve/protocol'
9
13
  require 'rserve/packet'
10
14
  require 'rserve/talk'
@@ -14,3 +18,4 @@ require 'rserve/connection'
14
18
  require 'rserve/rlist'
15
19
  require 'rserve/rfactor'
16
20
 
21
+
@@ -236,8 +236,8 @@ module Rserve
236
236
 
237
237
  # hack for factors
238
238
  if (!get_attr.nil?)
239
- ca = get_attr().as_list().at("class");
240
- ls = get_attr().as_list().at("levels");
239
+ ca = get_attr().as_list["class"]
240
+ ls = get_attr().as_list["levels"]
241
241
  if (!ca.nil? and !ls.nil? and ca.as_string=="factor")
242
242
  # R uses 1-based index, Java (and Ruby) uses 0-based one
243
243
  @cont = REXP::Factor.new(d, ls.as_strings(), get_attr)
@@ -275,8 +275,7 @@ module Rserve
275
275
  name=nf.cont.as_string if(nf.cont.symbol? or nf.cont.string?)
276
276
  end
277
277
  if name.nil?
278
-
279
- l.add(lc.cont)
278
+ l.push(lc.cont)
280
279
  else
281
280
  l.put(name,lc.cont)
282
281
  end
data/lib/rserve/rexp.rb CHANGED
@@ -81,7 +81,9 @@ module Rserve
81
81
  def as_doubles; raise MismatchException,"double";end;
82
82
 
83
83
  # On Ruby, Float are stored in double precision
84
- alias :as_floats :as_doubles
84
+ def as_floats
85
+ as_doubles
86
+ end
85
87
 
86
88
  # returns the contents as an array of bytes (if supported by the represented object)
87
89
  def as_bytes; raise MismatchException , "byte";end;
@@ -115,8 +117,9 @@ module Rserve
115
117
  def as_double
116
118
  as_doubles[0]
117
119
  end
118
-
119
- alias :as_float :as_double
120
+ def as_float
121
+ as_double
122
+ end
120
123
  # convenience method corresponding to <code>asStrings()[0]</code>
121
124
  # @return first entry returned by {@link #asStrings}
122
125
  def as_string
@@ -147,8 +150,8 @@ module Rserve
147
150
  # @return an array of integers with corresponding dimensions or <code>null</code> if the object has no dimension attribute
148
151
  def dim
149
152
  begin
150
- return has_attribute?("dim") ? @attr.as_list['dim'].as_integers : nil;
151
- rescue MismatchException
153
+ return has_attribute?("dim") ? @attr.as_list['dim'].as_integers : nil;
154
+ rescue MismatchException
152
155
  # nothing to do
153
156
  end
154
157
  nil
@@ -158,7 +161,7 @@ module Rserve
158
161
  # @param klass class name
159
162
  # @return <code>true</code> if this object is of the class <code>klass</code>, <code>false</code> otherwise
160
163
  def inherits?(klass)
161
- return false if (!has_attribute? "class")
164
+ return false if (!has_attribute? "class")
162
165
  begin
163
166
  c = get_attribute("class").as_strings;
164
167
  if (!c.nil?)
@@ -227,35 +230,35 @@ module Rserve
227
230
  def to_ruby
228
231
  raise "You should implement this!"
229
232
  end
230
- end
231
- end
232
-
233
-
234
- require 'rserve/rexp/environment'
235
- require 'rserve/rexp/null'
236
- require 'rserve/rexp/unknown'
237
-
238
-
239
- require 'rserve/rexp/vector'
240
-
241
- require 'rserve/rexp/raw'
242
- require 'rserve/rexp/symbol'
243
- require 'rserve/rexp/string'
244
- require 'rserve/rexp/double'
245
- require 'rserve/rexp/integer'
246
- require 'rserve/rexp/logical'
247
-
248
- require 'rserve/rexp/factor'
233
+ end
234
+ end
249
235
 
250
- require 'rserve/rexp/genericvector'
251
- require 'rserve/rexp/expressionvector'
252
236
 
253
-
254
- require 'rserve/rexp/list'
255
- require 'rserve/rexp/language'
256
- require 'rserve/rexp/s4'
257
-
258
- require 'rserve/rexp/reference'
259
-
260
- require 'rserve/rexp/wrapper'
237
+ require 'rserve/rexp/environment'
238
+ require 'rserve/rexp/null'
239
+ require 'rserve/rexp/unknown'
240
+
241
+
242
+ require 'rserve/rexp/vector'
243
+
244
+ require 'rserve/rexp/raw'
245
+ require 'rserve/rexp/symbol'
246
+ require 'rserve/rexp/string'
247
+ require 'rserve/rexp/double'
248
+ require 'rserve/rexp/integer'
249
+ require 'rserve/rexp/logical'
250
+
251
+ require 'rserve/rexp/factor'
252
+
253
+ require 'rserve/rexp/genericvector'
254
+ require 'rserve/rexp/expressionvector'
255
+
256
+
257
+ require 'rserve/rexp/list'
258
+ require 'rserve/rexp/language'
259
+ require 'rserve/rexp/s4'
260
+
261
+ require 'rserve/rexp/reference'
262
+
263
+ require 'rserve/rexp/wrapper'
261
264
 
data/lib/rserve/rlist.rb CHANGED
@@ -1,150 +1,55 @@
1
1
  module Rserve
2
- class Rlist
3
- include Enumerable
4
- attr_reader :names
2
+ class Rlist < Array
3
+ include WithNames
5
4
  attr_reader :data
6
- def initialize(data=nil,n=nil)
5
+ def initialize(data=nil, n=nil)
7
6
  @names=nil
8
- @data=[]
9
- if data
10
- @data=case data
11
- when Array
12
- data
13
- when Numeric
14
- Array.new(data)
7
+ if data.nil?
8
+ super()
15
9
  else
16
- raise ArgumentError
10
+ case data
11
+ when Array
12
+ super(data)
13
+ when Numeric
14
+ super([data])
15
+ else
16
+ raise ArgumentError
17
+ end
17
18
  end
18
- end
19
+
19
20
  if n
20
- @names=Array.new(@data.size)
21
+ @names=Array.new(size)
21
22
  n.each_index {|i| @names[i]=n[i]} if n.respond_to? :each_index
22
23
  end
23
24
  end
24
- def named?
25
- !@names.nil?
26
- end
27
- def ==(o)
28
- #p "Comparing #{self.inspect} with #{o.inspect} gives #{o.is_a? Rlist and self.data==o.data and self.names==o.names}"
29
- o.is_a? Rlist and self.data==o.data and self.names==o.names
30
- end
31
- # Return element with name x or 0-index x
32
- def [](v)
33
- if v.is_a? String
34
- return nil if @names.nil? or v==""
35
- i=@names.index(v)
36
- return i.nil? ? nil : @data[i]
37
- elsif v.is_a? Integer
38
- return @data[v]
39
- else
40
- raise ArgumentError,"Should be String or Integer"
41
- end
42
- end
43
-
44
- def at(v)
45
- self.[](v)
46
- end
47
-
48
- def key_at(v)
49
- return nil if @names.nil?
50
- @names[v]
51
- end
52
- def size
53
- @data.size
54
- end
55
-
56
- def each
57
- @data.each do |v|
58
- yield v
59
- end
60
- end
61
-
62
- def set_key_at(i,value)
63
- if @names.nil?
64
- @names=Array.new
65
- end
66
- if @names.size<size
67
- (size-@names.size).times {@names.push(nil)}
68
- end
69
-
70
- @names[i]=value if i < size
71
-
72
- end
73
-
74
25
  def keys
75
26
  @names
76
27
  end
77
-
78
- def put(key,value)
79
- puts "rlist.put(#{key},#{value})" if $DEBUG
80
- if key.nil?
81
- add(value)
82
- return nil
83
- end
84
- if !@names.nil?
85
- p=names.index(key)
86
- if !p.nil?
87
- return @names[p]=value
88
- end
89
- end
90
- puts "add key and value" if $DEBUG
91
- i=size
92
- @names=Array.new(i) if(@names.nil?)
93
- @data.push(value)
94
- @names.push(key)
95
-
96
- end
97
- def add(a,b=nil)
98
- if b.nil?
99
- @data.push(a)
100
- @names=Array.new(@data.size-1) if @names.nil?
101
- @names.push(nil)
102
- else
103
- @data.insert(a,b)
104
- @names.insert(a,nil)
105
- end
106
- end
107
- def clear
108
- @data.clear
109
- @names=nil
28
+ # Returns the data without names, as Ruby objects
29
+ def to_a
30
+ self.map {|d| d.to_ruby}
110
31
  end
111
- def clone
112
- RList.new(@data,@names)
32
+ # Returns the data, as REXP
33
+ def data
34
+ self.map {|d| d}
113
35
  end
114
- def remove(elem)
115
- if elem.is_a? String
116
- i=@data.index(elem)
117
- elsif elem.is_a? Integer
118
- i=elem
119
- end
120
- return false if i.nil?
121
- @data.delete_at(i)
122
- @names.delete_at(i) unless @names.nil?
123
- @names=nil if size==0
124
- end
125
- # Returns data with appropiate ruby representation
126
- def to_a
127
- @data.map {|d|
128
- d.to_ruby
129
- }
36
+ def ==(o)
37
+ #p "Comparing #{self.inspect} with #{o.inspect} gives #{o.is_a? Rlist and self.data==o.data and self.names==o.names}"
38
+ o.is_a? Rlist and self.data==o.data and self.names==o.names
130
39
  end
131
- # Returns recursively a hash or array:
40
+
41
+
42
+ # Returns an Array with module WithNames included
132
43
  # * Unnamed list: returns an Array
133
44
  # * Named List: returns a Hash. Every element without explicit name receive
134
45
  # as key the number of element, 1-based
135
46
  #
136
47
 
137
48
  def to_ruby
138
- if names.nil? or names.all? {|v| v.nil?}
139
- to_a
140
- else
141
- h=Hash.new
142
- names.each_with_index {|name,i|
143
- key= (name=="" or name.nil?) ? i+1 : name
144
- h[key]=@data[i].to_ruby
145
- }
146
- h
147
- end
49
+ data=to_a
50
+ data.extend WithNames
51
+ data.names=@names
52
+ data
148
53
  end
149
54
  end
150
55
  end
@@ -0,0 +1,5 @@
1
+ module Rserve
2
+ module WithAttributes
3
+ attr_accessor :attributes
4
+ end
5
+ end
@@ -0,0 +1,109 @@
1
+ module Rserve
2
+ # Provides names to elements on an Array
3
+ module WithNames
4
+ attr_reader :names
5
+ def names=(v)
6
+ raise ArgumentError, "#size should be equal to object size" if !v.nil? and v.size!=self.size
7
+ raise ArgumentError, "element must be String or nil" unless v.nil? or v.all? {|v1| v1.nil? or v1.is_a? String}
8
+ @names=v
9
+ end
10
+ def push(v,name=nil)
11
+ @names||=Array.new(self.size)
12
+ (@names.size-self.size).times { @names.push(nil)}
13
+ @names.push(name)
14
+ super(v)
15
+ end
16
+ def inspect
17
+ "#<#{self.class}:#{self.object_id} #{super} names:#{@names.inspect}>"
18
+ end
19
+ def clear
20
+ @names=nil
21
+ super()
22
+ end
23
+ def delete_at(i)
24
+ unless @names.nil?
25
+ @names.delete_at(i)
26
+ end
27
+ super(i)
28
+ end
29
+ def pop
30
+ unless @names.nil?
31
+ @names.pop
32
+ end
33
+ super
34
+ end
35
+
36
+ def reverse!
37
+ unless @names.nil?
38
+ @names.reverse!
39
+ end
40
+ super
41
+ end
42
+ def shift
43
+ unless @names.nil?
44
+ @names.shift
45
+ end
46
+ super
47
+ end
48
+ def slice(*args)
49
+ sliced=super(*args)
50
+ unless @names.nil?
51
+ sliced.extend Rserve::WithNames
52
+ sliced.names=@names.slice(*args)
53
+ end
54
+ sliced
55
+ end
56
+ def named?
57
+ !@names.nil?
58
+ end
59
+ def to_a
60
+ Array.new(self)
61
+ end
62
+ def key_at(v)
63
+ @names.nil? ? nil : @names[v]
64
+ end
65
+ # Put a value on specific key
66
+ # If key exists, replaces element of apropiate index
67
+ # If key doesn't exists, works as push(value,key)
68
+ def put(key,value)
69
+ if key.nil?
70
+ add(value)
71
+ return nil
72
+ end
73
+
74
+ if !@names.nil?
75
+ pos=@names.index(key)
76
+ if !pos.nil?
77
+ return @names[pos]=value
78
+ end
79
+ end
80
+ push(value,key)
81
+ end
82
+ def __add(a,b=nil)
83
+ if b.nil?
84
+ @data.push(a)
85
+ @names=Array.new(@data.size-1) if @names.nil?
86
+ @names.push(nil)
87
+ else
88
+ @data.insert(a,b)
89
+ @names.insert(a,nil)
90
+ end
91
+ end
92
+ def [](v)
93
+ case v
94
+ when Integer
95
+ at(v)
96
+ when Array
97
+ raise "You must use something like v[[1]]" if v.size!=1 or !v[0].is_a? Integer
98
+ at(v[0]-1)
99
+ when String
100
+ if !@names.nil?
101
+ i=@names.index(v)
102
+ i.nil? ? nil : at(i)
103
+ else
104
+ nil
105
+ end
106
+ end
107
+ end
108
+ end
109
+ end
@@ -32,21 +32,21 @@ describe Rserve::Rlist do
32
32
  it "method to_a return an array with best ruby representation of data" do
33
33
  @l.to_a.should==['Fred',30,10,20,[1,2,3]]
34
34
  end
35
- it "method to_ruby returns a hash when all names are set" do
35
+ it "method to_ruby returns a named array when all names are set" do
36
36
  list=@r.eval("list(name='Fred', age=30)")
37
- list.to_ruby.should=={'name'=>'Fred','age'=>30}
37
+ a=['Fred',30]
38
+ a.extend Rserve::WithNames
39
+ a.names=['name','age']
40
+ list.to_ruby.should==a
38
41
  end
39
- it "method to_ruby returns a hash with numbers (1-based) replacing empty names" do
40
- list=@r.eval("list(name='Fred', age=30,'aaaa')")
41
- list.to_ruby.should=={'name'=>'Fred','age'=>30,3=>'aaaa'}
42
- end
43
- it "method to_ruby returns an array when no names are set" do
42
+ it "method to_ruby returns a simple array when no names are set" do
44
43
  list=@r.eval("list(10,20,30)")
45
44
  list.to_ruby.should==[10,20,30]
46
45
  end
47
46
  it "should allow recursive list" do
48
47
  list=@r.eval("list(l1=list(l11=1,l22=2),l2=list(3,4))").as_list
49
- list['l1'].to_ruby.should=={'l11'=>1,'l22'=>2}
48
+ list.names.should==['l1','l2']
49
+ list['l1'].to_ruby.should==[1,2]
50
50
  list['l2'].to_ruby.should==[3,4]
51
51
 
52
52
  end
@@ -0,0 +1,73 @@
1
+ require File.dirname(__FILE__)+"/spec_helper.rb"
2
+
3
+ describe Rserve::WithNames do
4
+ before do
5
+ @a=[1,2,3,4]
6
+ @a.extend Rserve::WithNames
7
+ end
8
+ it "should return nil without names" do
9
+ @a.names.should be_nil
10
+ end
11
+ describe "with incorrect naming" do
12
+ it "should raise an error with names array of another size" do
13
+ lambda {@a.names=["1","2"]}.should raise_exception
14
+ end
15
+ it "should raise an error with names array !(String or nil) " do
16
+ lambda {@a.names=[1,"a","b","c"]}.should raise_exception
17
+ lambda {@a.names=[nil,"a","b","c"]}.should_not raise_exception
18
+ end
19
+ end
20
+ describe "correct naming" do
21
+ before do
22
+ @a.names=['a','b','c',nil]
23
+ end
24
+ it "should set names and return them without problems" do
25
+ @a.names.should==['a','b','c',nil]
26
+ end
27
+ it "should return correct values with 0-index([x])" do
28
+ @a[0].should==1
29
+ @a[3].should==4
30
+ end
31
+ it "should return correct values with 1-index syntactic sugar ([[x]])" do
32
+ @a[[1]].should==1
33
+ @a[[4]].should==4
34
+ end
35
+ it "should return with names(['x'])" do
36
+ @a['a'].should==1
37
+ @a['b'].should==2
38
+ end
39
+ it "should push with or without name" do
40
+ @a.push(5)
41
+ @a.names.should==['a','b','c',nil,nil]
42
+ @a.push(6,'f')
43
+ @a.names.should==['a','b','c',nil,nil,'f']
44
+ end
45
+ it "method clear should delete names" do
46
+ @a.clear
47
+ @a.names.should be_nil
48
+ end
49
+ it "should delete_at names" do
50
+ @a.delete_at(0)
51
+ @a.should==[2,3,4]
52
+ @a.names.should==["b","c",nil]
53
+ end
54
+ it "should pop names" do
55
+ @a.pop
56
+ @a.names.should==['a','b','c']
57
+ end
58
+ it "should shift names" do
59
+ @a.shift
60
+ @a.names.should==['b','c',nil]
61
+ end
62
+ it "should reverse! names" do
63
+ @a.reverse!
64
+ @a.names.should==[nil,'c','b','a']
65
+ end
66
+ it "should slice names" do
67
+ b=@a.slice(1,2)
68
+ b.should==[2,3]
69
+ b.names.should==['b','c']
70
+ end
71
+ end
72
+
73
+ end
metadata CHANGED
@@ -5,8 +5,8 @@ version: !ruby/object:Gem::Version
5
5
  segments:
6
6
  - 0
7
7
  - 1
8
- - 6
9
- version: 0.1.6
8
+ - 7
9
+ version: 0.1.7
10
10
  platform: ruby
11
11
  authors:
12
12
  - Claudio Bustos
@@ -35,7 +35,7 @@ cert_chain:
35
35
  rpP0jjs0
36
36
  -----END CERTIFICATE-----
37
37
 
38
- date: 2010-05-27 00:00:00 -04:00
38
+ date: 2010-05-28 00:00:00 -04:00
39
39
  default_executable:
40
40
  dependencies:
41
41
  - !ruby/object:Gem::Dependency
@@ -77,16 +77,20 @@ executables: []
77
77
  extensions: []
78
78
 
79
79
  extra_rdoc_files:
80
+ - Examples.txt
80
81
  - History.txt
81
82
  - Manifest.txt
82
83
  - README.txt
83
84
  files:
84
85
  - .autotest
85
86
  - .gitignore
87
+ - Examples.txt
86
88
  - History.txt
87
89
  - Manifest.txt
88
90
  - README.txt
89
91
  - Rakefile
92
+ - examples/hello_world.rb
93
+ - examples/lowless.rb
90
94
  - lib/rserve.rb
91
95
  - lib/rserve/connection.rb
92
96
  - lib/rserve/engine.rb
@@ -115,6 +119,8 @@ files:
115
119
  - lib/rserve/rfactor.rb
116
120
  - lib/rserve/rlist.rb
117
121
  - lib/rserve/talk.rb
122
+ - lib/rserve/withattributes.rb
123
+ - lib/rserve/withnames.rb
118
124
  - spec/rserve_connection_spec.rb
119
125
  - spec/rserve_double_spec.rb
120
126
  - spec/rserve_integer_spec.rb
@@ -128,6 +134,7 @@ files:
128
134
  - spec/rserve_rlist_spec.rb
129
135
  - spec/rserve_spec.rb
130
136
  - spec/rserve_talk_spec.rb
137
+ - spec/rserve_withnames_spec.rb
131
138
  - spec/spec.opts
132
139
  - spec/spec_helper.rb
133
140
  has_rdoc: true
@@ -167,6 +174,7 @@ test_files:
167
174
  - spec/rserve_rfactor_spec.rb
168
175
  - spec/rserve_connection_spec.rb
169
176
  - spec/rserve_double_spec.rb
177
+ - spec/rserve_withnames_spec.rb
170
178
  - spec/rserve_packet_spec.rb
171
179
  - spec/rserve_rexpfactory_spec.rb
172
180
  - spec/rserve_rexp_spec.rb
metadata.gz.sig CHANGED
Binary file