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.
- data.tar.gz.sig +1 -2
- data/.gitignore +1 -0
- data/History.txt +15 -2
- data/Manifest.txt +8 -0
- data/README.txt +41 -19
- data/lib/rserve.rb +1 -1
- data/lib/rserve/connection.rb +152 -69
- data/lib/rserve/engine.rb +9 -9
- data/lib/rserve/packet.rb +2 -2
- data/lib/rserve/protocol.rb +51 -46
- data/lib/rserve/protocol/rexpfactory.rb +659 -366
- data/lib/rserve/rexp.rb +175 -156
- data/lib/rserve/rexp/double.rb +45 -38
- data/lib/rserve/rexp/environment.rb +40 -0
- data/lib/rserve/rexp/expressionvector.rb +9 -0
- data/lib/rserve/rexp/genericvector.rb +5 -3
- data/lib/rserve/rexp/integer.rb +38 -38
- data/lib/rserve/rexp/language.rb +2 -2
- data/lib/rserve/rexp/list.rb +3 -0
- data/lib/rserve/rexp/logical.rb +17 -4
- data/lib/rserve/rexp/null.rb +20 -14
- data/lib/rserve/rexp/raw.rb +19 -0
- data/lib/rserve/rexp/reference.rb +42 -0
- data/lib/rserve/rexp/s4.rb +10 -0
- data/lib/rserve/rexp/string.rb +5 -3
- data/lib/rserve/rexp/symbol.rb +3 -0
- data/lib/rserve/rexp/vector.rb +30 -15
- data/lib/rserve/rexp/wrapper.rb +58 -0
- data/lib/rserve/rfactor.rb +10 -10
- data/lib/rserve/rlist.rb +129 -100
- data/lib/rserve/talk.rb +61 -61
- data/spec/rserve_connection_spec.rb +99 -33
- data/spec/rserve_double_spec.rb +28 -15
- data/spec/rserve_integer_spec.rb +24 -15
- data/spec/rserve_logical_spec.rb +21 -12
- data/spec/rserve_protocol_spec.rb +7 -7
- data/spec/rserve_rexp_spec.rb +3 -3
- data/spec/rserve_rexp_wrapper_spec.rb +36 -0
- data/spec/rserve_rexpfactory_spec.rb +86 -20
- data/spec/rserve_rfactor_spec.rb +2 -2
- data/spec/rserve_rlist_spec.rb +53 -0
- data/spec/rserve_spec.rb +8 -5
- data/spec/rserve_talk_spec.rb +7 -7
- data/spec/spec_helper.rb +1 -0
- metadata +13 -3
- metadata.gz.sig +0 -0
data/lib/rserve/rexp.rb
CHANGED
@@ -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
|
-
|
23
|
-
|
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
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
|
88
|
-
|
89
|
-
|
90
|
-
|
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
|
-
|
93
|
-
|
94
|
-
|
95
|
-
|
96
|
-
|
97
|
-
|
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
|
-
|
100
|
-
|
101
|
-
|
102
|
-
|
103
|
-
|
104
|
-
|
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
|
-
|
107
|
-
|
108
|
-
|
109
|
-
|
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
|
-
|
112
|
-
|
113
|
-
|
114
|
-
|
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
|
-
|
117
|
-
|
118
|
-
|
119
|
-
|
120
|
-
|
121
|
-
|
122
|
-
|
123
|
-
|
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
|
-
|
127
|
-
|
128
|
-
|
129
|
-
|
130
|
-
|
131
|
-
|
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
|
-
|
134
|
-
|
135
|
-
|
136
|
-
|
137
|
-
|
138
|
-
|
139
|
-
|
140
|
-
|
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
|
-
|
150
|
+
return has_attribute?("dim") ? @attr.as_list['dim'].as_integers : nil;
|
143
151
|
rescue MismatchException
|
144
|
-
|
145
|
-
end
|
146
|
-
|
147
|
-
|
148
|
-
|
149
|
-
|
150
|
-
|
151
|
-
|
152
|
-
|
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
|
-
|
156
|
-
|
157
|
-
|
158
|
-
|
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
|
-
|
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
|
-
|
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
|
-
|
188
|
-
|
189
|
-
|
190
|
-
|
191
|
-
|
192
|
-
|
193
|
-
|
194
|
-
|
195
|
-
|
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
|
-
|
200
|
-
|
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
|
-
|
211
|
-
|
212
|
-
|
213
|
-
|
214
|
-
|
215
|
-
|
216
|
-
|
217
|
-
|
218
|
-
|
219
|
-
|
220
|
-
|
221
|
-
|
222
|
-
|
223
|
-
|
224
|
-
end
|
225
|
-
|
226
|
-
|
227
|
-
|
228
|
-
|
229
|
-
|
230
|
-
|
231
|
-
|
232
|
-
|
233
|
-
|
234
|
-
require 'rserve/rexp/
|
235
|
-
require 'rserve/rexp/
|
236
|
-
|
237
|
-
|
238
|
-
|
239
|
-
|
240
|
-
require 'rserve/rexp/
|
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
|
|
data/lib/rserve/rexp/double.rb
CHANGED
@@ -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
|
-
#
|
6
|
-
|
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
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
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
|