rserve-client 0.1.5 → 0.1.6

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (46) hide show
  1. data.tar.gz.sig +1 -2
  2. data/.gitignore +1 -0
  3. data/History.txt +15 -2
  4. data/Manifest.txt +8 -0
  5. data/README.txt +41 -19
  6. data/lib/rserve.rb +1 -1
  7. data/lib/rserve/connection.rb +152 -69
  8. data/lib/rserve/engine.rb +9 -9
  9. data/lib/rserve/packet.rb +2 -2
  10. data/lib/rserve/protocol.rb +51 -46
  11. data/lib/rserve/protocol/rexpfactory.rb +659 -366
  12. data/lib/rserve/rexp.rb +175 -156
  13. data/lib/rserve/rexp/double.rb +45 -38
  14. data/lib/rserve/rexp/environment.rb +40 -0
  15. data/lib/rserve/rexp/expressionvector.rb +9 -0
  16. data/lib/rserve/rexp/genericvector.rb +5 -3
  17. data/lib/rserve/rexp/integer.rb +38 -38
  18. data/lib/rserve/rexp/language.rb +2 -2
  19. data/lib/rserve/rexp/list.rb +3 -0
  20. data/lib/rserve/rexp/logical.rb +17 -4
  21. data/lib/rserve/rexp/null.rb +20 -14
  22. data/lib/rserve/rexp/raw.rb +19 -0
  23. data/lib/rserve/rexp/reference.rb +42 -0
  24. data/lib/rserve/rexp/s4.rb +10 -0
  25. data/lib/rserve/rexp/string.rb +5 -3
  26. data/lib/rserve/rexp/symbol.rb +3 -0
  27. data/lib/rserve/rexp/vector.rb +30 -15
  28. data/lib/rserve/rexp/wrapper.rb +58 -0
  29. data/lib/rserve/rfactor.rb +10 -10
  30. data/lib/rserve/rlist.rb +129 -100
  31. data/lib/rserve/talk.rb +61 -61
  32. data/spec/rserve_connection_spec.rb +99 -33
  33. data/spec/rserve_double_spec.rb +28 -15
  34. data/spec/rserve_integer_spec.rb +24 -15
  35. data/spec/rserve_logical_spec.rb +21 -12
  36. data/spec/rserve_protocol_spec.rb +7 -7
  37. data/spec/rserve_rexp_spec.rb +3 -3
  38. data/spec/rserve_rexp_wrapper_spec.rb +36 -0
  39. data/spec/rserve_rexpfactory_spec.rb +86 -20
  40. data/spec/rserve_rfactor_spec.rb +2 -2
  41. data/spec/rserve_rlist_spec.rb +53 -0
  42. data/spec/rserve_spec.rb +8 -5
  43. data/spec/rserve_talk_spec.rb +7 -7
  44. data/spec/spec_helper.rb +1 -0
  45. metadata +13 -3
  46. metadata.gz.sig +0 -0
@@ -1,242 +1,261 @@
1
1
  module Rserve
2
2
  # Basic class representing an object of any type in R. Each type in R in represented by a specific subclass.
3
- #
3
+ #
4
4
  # This class defines basic accessor methods (<tt>as</tt><i>XXX</i>), type check methods (<tt>is</tt><i>XXX</i>), gives access to attributes ({@link #getAttribute}, {@link #hasAttribute}) as well as several convenience methods. If a given method is not applicable to a particular type, it will throw the {@link MismatchException} exception.
5
5
  #
6
6
  # This root class will throw on any accessor call and returns <code>false</code> for all type methods. This allows subclasses to override accessor and type methods selectively.
7
- #
7
+ #
8
8
  class REXP
9
9
  MismatchException= Class.new(Exception)
10
10
  attr_reader :attr
11
11
  def initialize(attr=nil)
12
+ # Sorry for this, but I think is necessary to maintain sanity of attributes
13
+ raise ArgumentError, "Attribute should be a REXP::List, #{attr.class} provided" unless attr.nil? or attr.is_a? REXP::List
12
14
  @attr=attr
13
15
  end
14
- # specifies how many items of a vector or list will be displayed in {@link #toDebugString} */
16
+ # specifies how many items of a vector or list will be displayed in {@link #toDebugString}
15
17
  MaxDebugItems = 32
16
18
  # :section: type checks
17
19
  # check whether the <code>REXP</code> object is a character vector (string)
18
- # @return <code>true</code> if the receiver is a character vector, <code>false</code> otherwise */
19
-
20
+ # @return <code>true</code> if the receiver is a character vector, <code>false</code> otherwise
21
+
20
22
  def string?;return false;end
21
23
 
22
- # # check whether the <code>REXP</code> object is a numeric vector
23
- # @return <code>true</code> if the receiver is a numeric vector, <code>false</code> otherwise */
24
+ # # check whether the <code>REXP</code> object is a numeric vector
25
+ # @return <code>true</code> if the receiver is a numeric vector, <code>false</code> otherwise
24
26
 
25
27
  def numeric?;false;end
26
28
  # check whether the <code>REXP</code> object is an integer vector
27
- # @return <code>true</code> if the receiver is an integer vector, <code>false</code> otherwise */
29
+ # @return <code>true</code> if the receiver is an integer vector, <code>false</code> otherwise
28
30
  def integer?;false;end
29
31
  # check whether the <code>REXP</code> object is NULL
30
- # @return <code>true</code> if the receiver is NULL, <code>false</code> otherwise */
32
+ # @return <code>true</code> if the receiver is NULL, <code>false</code> otherwise
31
33
  def null?;false;end
32
34
  # check whether the <code>REXP</code> object is a factor
33
- # @return <code>true</code> if the receiver is a factor, <code>false</code> otherwise */
35
+ # @return <code>true</code> if the receiver is a factor, <code>false</code> otherwise
34
36
  def factor?;false;end
35
37
  # check whether the <code>REXP</code> object is a list (either generic vector or a pairlist - i.e. {@link #asList()} will succeed)
36
- # @return <code>true</code> if the receiver is a generic vector or a pair-list, <code>false</code> otherwise */
38
+ # @return <code>true</code> if the receiver is a generic vector or a pair-list, <code>false</code> otherwise
37
39
  def list?;false;end
38
40
  # check whether the <code>REXP</code> object is a pair-list
39
- # @return <code>true</code> if the receiver is a pair-list, <code>false</code> otherwise */
41
+ # @return <code>true</code> if the receiver is a pair-list, <code>false</code> otherwise
40
42
  def pair_list?;false;end
41
43
  # check whether the <code>REXP</code> object is a logical vector
42
44
  # @return <code>true</code> if the receiver is a logical vector, <code>false</code> otherwise */
43
45
  def logical?;false;end
44
46
  # check whether the <code>REXP</code> object is an environment
45
- # @return <code>true</code> if the receiver is an environment, <code>false</code> otherwise */
47
+ # @return <code>true</code> if the receiver is an environment, <code>false</code> otherwise
46
48
  def environment?;false;end
47
49
  # check whether the <code>REXP</code> object is a language object
48
- # @return <code>true</code> if the receiver is a language object, <code>false</code> otherwise */
50
+ # @return <code>true</code> if the receiver is a language object, <code>false</code> otherwise
49
51
  def language?;false;end
50
52
  # check whether the <code>REXP</code> object is an expression vector
51
- # @return <code>true</code> if the receiver is an expression vector, <code>false</code> otherwise */
53
+ # @return <code>true</code> if the receiver is an expression vector, <code>false</code> otherwise
52
54
  def expression?;false;end
53
55
  # check whether the <code>REXP</code> object is a symbol
54
- # @return <code>true</code> if the receiver is a symbol, <code>false</code> otherwise */
56
+ # @return <code>true</code> if the receiver is a symbol, <code>false</code> otherwise
55
57
  def symbol?;false;end
56
58
  # check whether the <code>REXP</code> object is a vector
57
- # @return <code>true</code> if the receiver is a vector, <code>false</code> otherwise */
59
+ # @return <code>true</code> if the receiver is a vector, <code>false</code> otherwise
58
60
  def vector?;false;end
59
61
  # check whether the <code>REXP</code> object is a raw vector
60
- # @return <code>true</code> if the receiver is a raw vector, <code>false</code> otherwise */
62
+ # @return <code>true</code> if the receiver is a raw vector, <code>false</code> otherwise
61
63
  def raw?;false;end
62
64
  # check whether the <code>REXP</code> object is a complex vector
63
- # @return <code>true</code> if the receiver is a complex vector, <code>false</code> otherwise */
65
+ # @return <code>true</code> if the receiver is a complex vector, <code>false</code> otherwise
64
66
  def complex?;false;end
65
67
  # check whether the <code>REXP</code> object is a recursive obejct
66
- # @return <code>true</code> if the receiver is a recursive object, <code>false</code> otherwise */
68
+ # @return <code>true</code> if the receiver is a recursive object, <code>false</code> otherwise
67
69
  def recursive?;false;end
68
70
  # check whether the <code>REXP</code> object is a reference to an R object
69
- # @return <code>true</code> if the receiver is a reference, <code>false</code> otherwise */
71
+ # @return <code>true</code> if the receiver is a reference, <code>false</code> otherwise
70
72
  def reference?;false;end
71
-
72
- # :section: basic accessor methods
73
- # returns the contents as an array of Strings (if supported by the represented object)
74
- def as_strings;raise MismatchException, "String";end
75
- # returns the contents as an array of integers (if supported by the represented object) */
76
-
77
- def as_integers; raise MismatchException, "int";end;
78
- # returns the contents as an array of doubles (if supported by the represented object) */
79
- def as_doubles; raise MismatchException,"double";end;
80
- # returns the contents as an array of bytes (if supported by the represented object) */
81
- def as_bytes; raise MismatchException , "byte";end;
82
- # returns the contents as a (named) list (if supported by the represented object) */
83
- def as_list; raise MismatchException,"list";end;
84
- # returns the contents as a factor (if supported by the represented object) */
85
- def as_factor; raise MismatchException,"factor";end;
86
-
87
- # returns the length of a vector object. Note that we use R semantics here, i.e. a matrix will have a length of <i>m * n</i> since it is represented by a single vector (see {@link #dim} for retrieving matrix and multidimentional-array dimensions).
88
- # * @return length (number of elements) in a vector object
89
- # * @throws MismatchException if this is not a vector object */
90
- def length()
73
+
74
+ # :section: basic accessor methods
75
+ # returns the contents as an array of Strings (if supported by the represented object)
76
+ def as_strings;raise MismatchException, "String";end
77
+ # returns the contents as an array of integers (if supported by the represented object)
78
+
79
+ def as_integers; raise MismatchException, "int";end;
80
+ # returns the contents as an array of doubles (if supported by the represented object)
81
+ def as_doubles; raise MismatchException,"double";end;
82
+
83
+ # On Ruby, Float are stored in double precision
84
+ alias :as_floats :as_doubles
85
+
86
+ # returns the contents as an array of bytes (if supported by the represented object)
87
+ def as_bytes; raise MismatchException , "byte";end;
88
+ # returns the contents as a (named) list (if supported by the represented object)
89
+ def as_list; raise MismatchException,"list";end;
90
+ # returns the contents as a factor (if supported by the represented object)
91
+ def as_factor; raise MismatchException,"factor";end;
92
+
93
+ # returns the length of a vector object. Note that we use R semantics here, i.e. a matrix will have a length of <i>m * n</i> since it is represented by a single vector (see {@link #dim} for retrieving matrix and multidimentional-array dimensions).
94
+ # * @return length (number of elements) in a vector object
95
+ # * @throws MismatchException if this is not a vector object
96
+ def length()
91
97
  raise MismatchException, "vector";
92
- end
93
-
94
- # returns a boolean vector of the same length as this vector with <code>true</code> for NA values and <code>false</code> for any other values
95
- # * @return a boolean vector of the same length as this vector with <code>true</code> for NA values and <code>false</code> for any other values
96
- # * @throws MismatchException if this is not a vector object */
97
- def na?
98
+ end
99
+
100
+ # returns a boolean vector of the same length as this vector with <code>true</code> for NA values and <code>false</code> for any other values
101
+ # * @return a boolean vector of the same length as this vector with <code>true</code> for NA values and <code>false</code> for any other values
102
+ # * @throws MismatchException if this is not a vector object
103
+ def na?
98
104
  raise MismatchException, "vector"
99
- end
100
-
101
- # :section: convenience accessor methods
102
- # convenience method corresponding to <code>as_integer()[0]</code>
103
- # @return first entry returned by {@link #as_integer} */
104
- def as_integer
105
+ end
106
+
107
+ # :section: convenience accessor methods
108
+ # convenience method corresponding to <code>as_integer()[0]</code>
109
+ # @return first entry returned by {@link #as_integer}
110
+ def as_integer
105
111
  as_integers[0]
106
- end
107
- # convenience method corresponding to <code>asDoubles()[0]</code>
108
- # @return first entry returned by {@link #asDoubles} */
109
- def as_double
112
+ end
113
+ # convenience method corresponding to <code>asDoubles()[0]</code>
114
+ # @return first entry returned by {@link #asDoubles}
115
+ def as_double
110
116
  as_doubles[0]
111
- end
112
- # convenience method corresponding to <code>asStrings()[0]</code>
113
- # @return first entry returned by {@link #asStrings} */
114
- def as_string
117
+ end
118
+
119
+ alias :as_float :as_double
120
+ # convenience method corresponding to <code>asStrings()[0]</code>
121
+ # @return first entry returned by {@link #asStrings}
122
+ def as_string
115
123
  as_strings[0]
116
- end
117
- # // methods common to all REXPs
118
-
119
- # retrieve an attribute of the given name from this object
120
- # * @param name attribute name
121
- # * @return attribute value or <code>null</code> if the attribute does not exist */
122
-
123
- def get_attribute(name)
124
+ end
125
+ # // methods common to all REXPs
126
+
127
+ # retrieve an attribute of the given name from this object
128
+ # * @param name attribute name
129
+ # * @return attribute value or <code>null</code> if the attribute does not exist
130
+
131
+ def get_attribute(name)
124
132
  nil if @attr.nil? or !@attr.list?
125
133
  @attr.as_list[name]
126
- end
127
-
128
- # checks whether this obejct has a given attribute
129
- # * @param name attribute name
130
- # * @return <code>true</code> if the attribute exists, <code>false</code> otherwise */
131
- def has_attribute? (name)
134
+ end
135
+
136
+ # checks whether this obejct has a given attribute
137
+ # * @param name attribute name
138
+ # * @return <code>true</code> if the attribute exists, <code>false</code> otherwise
139
+ def has_attribute? (name)
132
140
  return (!@attr.nil? and @attr.list? and !@attr.as_list[name].nil?);
133
- end
134
-
135
-
136
- # :section: helper methods common to all REXPs
137
-
138
- # returns dimensions of the object (as determined by the "<code>dim</code>" attribute)
139
- # @return an array of integers with corresponding dimensions or <code>null</code> if the object has no dimension attribute */
140
- def dim
141
+ end
142
+
143
+
144
+ # :section: helper methods common to all REXPs
145
+
146
+ # returns dimensions of the object (as determined by the "<code>dim</code>" attribute)
147
+ # @return an array of integers with corresponding dimensions or <code>null</code> if the object has no dimension attribute
148
+ def dim
141
149
  begin
142
- return has_attribute?("dim") ? @attr.as_list['dim'].as_integers : nil;
150
+ return has_attribute?("dim") ? @attr.as_list['dim'].as_integers : nil;
143
151
  rescue MismatchException
144
- # nothing to do
145
- end
146
- nil
147
- end
148
-
149
- # determines whether this object inherits from a given class in the same fashion as the <code>inherits()</code> function in R does (i.e. ignoring S4 inheritance)
150
- # @param klass class name
151
- # @return <code>true</code> if this object is of the class <code>klass</code>, <code>false</code> otherwise */
152
- def inherits?(klass)
152
+ # nothing to do
153
+ end
154
+ nil
155
+ end
156
+
157
+ # determines whether this object inherits from a given class in the same fashion as the <code>inherits()</code> function in R does (i.e. ignoring S4 inheritance)
158
+ # @param klass class name
159
+ # @return <code>true</code> if this object is of the class <code>klass</code>, <code>false</code> otherwise
160
+ def inherits?(klass)
153
161
  return false if (!has_attribute? "class")
154
162
  begin
155
- c = get_attribute("class").as_strings;
156
- if (!c.nil?)
157
- return c.any? {|v| v.equals klass}
158
- end
163
+ c = get_attribute("class").as_strings;
164
+ if (!c.nil?)
165
+ return c.any? {|v| v.equals klass}
166
+ end
159
167
  rescue MismatchException
160
168
  end
161
- return false;
162
- end
163
-
164
-
165
-
166
- # returns a string description of the object
167
- # @return string describing the object - it can be of an arbitrary form and used only for debugging (do not confuse with {@link #asString()} for accessing string REXPs) */
168
- def to_s
169
- return (!@attr.nil?) ? "+" : ""
169
+ return false;
170
170
  end
171
+
171
172
 
173
+
172
174
  # returns representation that it useful for debugging (e.g. it includes attributes and may include vector values -- see {@link #maxDebugItems})
173
175
  # @return extended description of the obejct -- it may include vector values
174
- def to_debug_string
175
- (!@attr.nil?) ? (("<"+@attr.to_debug_string()+">")+to_s()) : to_s
176
+ def to_debug_string
177
+ (!@attr.nil?) ? (("<"+@attr.to_debug_string()+">")+to_s()) : to_s
176
178
  end
177
179
 
178
180
 
179
-
180
181
  #//======= complex convenience methods
181
182
  # returns the content of the REXP as a ruby matrix of doubles (2D-array: m[rows][cols]). You could use Matrix.rows(result) to create
182
183
  # a ruby matrix.
183
184
  # Matrix(c.eval("matrix(c(1,2,3,4,5,6),2,3)").as_double_matrix());</code>
184
185
  #
185
- # @return 2D array of doubles in the form double[rows][cols] or <code>null</code> if the contents is no 2-dimensional matrix of doubles */
186
- def as_double_matrix()
187
- ct = as_doubles()
188
- dim = get_attribute "dim"
189
- raise MismatchException, "matrix (dim attribute missing)" if dim.nil?
190
- ds = dim.as_integers
191
- raise MismatchException, "matrix (wrong dimensionality)" if (ds.length!=2)
192
- m,n = ds[0], ds[1]
193
- # R stores matrices as matrix(c(1,2,3,4),2,2) = col1:(1,2), col2:(3,4)
194
- # we need to copy everything, since we create 2d array from 1d array
195
- r=m.times.map {|i| n.times.map {|j| ct[j*n+i]}}
186
+ # @return 2D array of doubles in the form double[rows][cols] or <code>null</code> if the contents is no 2-dimensional matrix of doubles
187
+ def as_double_matrix()
188
+ ct = as_doubles()
189
+ dim = get_attribute "dim"
190
+ raise MismatchException, "matrix (dim attribute missing)" if dim.nil?
191
+ ds = dim.as_integers
192
+ raise MismatchException, "matrix (wrong dimensionality)" if (ds.length!=2)
193
+ m,n = ds[0], ds[1]
194
+ # R stores matrices as matrix(c(1,2,3,4),2,2) = col1:(1,2), col2:(3,4)
195
+ # we need to copy everything, since we create 2d array from 1d array
196
+ r=m.times.map {|i| n.times.map {|j| ct[j*n+i]}}
196
197
  end
197
198
  # Returns a standard library's matrix
198
199
  def as_matrix
199
- require 'matrix'
200
- Matrix.rows(as_double_matrix)
200
+ require 'matrix'
201
+ Matrix.rows(as_double_matrix)
201
202
  end
202
203
 
203
204
  # :section: tools
204
-
205
+
205
206
  # creates a data frame object from a list object using integer row names
206
207
  # * @param l a (named) list of vectors ({@link REXPVector} subclasses), each element corresponds to a column and all elements must have the same length
207
208
  # * @return a data frame object
208
- # * @throws MismatchException if the list is empty or any of the elements is not a vector */
209
+ # * @throws MismatchException if the list is empty or any of the elements is not a vector
209
210
  def create_data_frame(l)
210
- raise(MismatchException, "data frame (must have dim>0)") if l.nil? or l.size<1
211
- raise MismatchException, "data frame (contents must be vectors)" if (!(l[0].is_a? REXP::Vector))
212
- fe = l[0]
213
- return REXP::GenericVector.new(l,
214
- REXP::List.new(
215
- RList.new(
216
- [
217
- REXP::String.new("data.frame"),
218
- REXP::String.new(l.keys()),
219
- REXP::Integer.new([REXP::Integer.NA, -fe.length()])
220
- ],
221
- ["class", "names", "row.names" ])
222
- )
223
- )
224
- end
225
- end
226
- end
227
-
228
- require 'rserve/rexp/vector'
229
- require 'rserve/rexp/null'
230
- require 'rserve/rexp/genericvector'
231
- require 'rserve/rexp/integer'
232
- require 'rserve/rexp/factor'
233
-
234
- require 'rserve/rexp/double'
235
- require 'rserve/rexp/list'
236
- require 'rserve/rexp/language'
237
- require 'rserve/rexp/unknown'
238
-
239
- require 'rserve/rexp/logical'
240
- require 'rserve/rexp/string'
241
- require 'rserve/rexp/symbol'
211
+ raise(MismatchException, "data frame (must have dim>0)") if l.nil? or l.size<1
212
+ raise MismatchException, "data frame (contents must be vectors)" if (!(l[0].is_a? REXP::Vector))
213
+ fe = l[0]
214
+ return REXP::GenericVector.new(l,
215
+ REXP::List.new(
216
+ RList.new(
217
+ [
218
+ REXP::String.new("data.frame"),
219
+ REXP::String.new(l.keys()),
220
+ REXP::Integer.new([REXP::Integer.NA, -fe.length()])
221
+ ],
222
+ ["class", "names", "row.names" ])
223
+ )
224
+ )
225
+ end
226
+ # Retrieves the best Ruby representation of data
227
+ def to_ruby
228
+ raise "You should implement this!"
229
+ 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'
249
+
250
+ require 'rserve/rexp/genericvector'
251
+ require 'rserve/rexp/expressionvector'
252
+
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'
242
261
 
@@ -1,47 +1,54 @@
1
+ require 'rbconfig'
1
2
  module Rserve
2
3
  class REXP
3
4
  class Double < REXP::Vector
4
5
  attr_reader :payload
5
- # In Java, you only need to add L at last :(
6
- NA = 0x100000000007a2000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
6
+ # NA is arch dependent
7
+ case Config::CONFIG['arch']
8
+ when 'i686-linux'
9
+ NA = 269653970229425383598692395468593241088322026492507901905402939417320933254485890939796955099302180188971623023005661539310855695935759376615857567599472873400528811349204333736152257830107446553333670133666606746438802800063353690283455789426038632208916715592554825644961573453826957827246636338344317943808
10
+ else
11
+ NA = 0x100000000007a2000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
12
+ end
13
+
7
14
  def initialize(data, attrs=nil)
8
15
  @payload=case data
9
- when Numeric
10
- [data.to_f]
11
- when Array
12
- data
13
- else
14
- raise ArgumentError, "Should be Numeric or Array"
15
- end
16
- super(attrs)
17
- end
18
- def length
19
- payload.length
20
- end
21
- def integer?
22
- true
23
- end
24
- def numeric?
25
- true
26
- end
27
- def as_integers
28
- @payload.map(&:to_i)
29
- end
30
- def as_doubles
31
- @payload
32
- end
33
- def as_strings
34
- @payload.map {|v| v.to_f.to_s}
35
- end
36
-
37
- def na?(value=nil)
38
- return value == NA unless value.nil?
39
- @payload.map {|v| v==NA}
40
- end
41
- def to_debug_string
42
- t=super
43
- t << "{" << @payload.map(&:to_s).join(",") << "}"
44
- end
16
+ when Numeric
17
+ [data.to_f]
18
+ when Array
19
+ data
20
+ else
21
+ raise ArgumentError, "Should be Numeric or Array"
22
+ end
23
+ super(attrs)
24
+ end
25
+ def length
26
+ payload.length
27
+ end
28
+ def integer?
29
+ true
30
+ end
31
+ def numeric?
32
+ true
33
+ end
34
+ def as_integers
35
+ @payload.map(&:to_i)
36
+ end
37
+ def as_doubles
38
+ @payload.map(&:to_f)
39
+ end
40
+ def as_strings
41
+ @payload.map {|v| v.to_f.to_s}
42
+ end
43
+
44
+ def na?(value=nil)
45
+ return value == NA unless value.nil?
46
+ @payload.map {|v| v==NA}
47
+ end
48
+ def to_debug_string
49
+ t=super
50
+ t << "{" << @payload.map(&:to_s).join(",") << "}"
45
51
  end
46
52
  end
47
53
  end
54
+ end