rserve-client 0.1.5 → 0.1.6

Sign up to get free protection for your applications and to get access to all the features.
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