fancy 0.3.3 → 0.4.0
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/README.md +14 -14
- data/Rakefile +16 -4
- data/bin/fancy +3 -0
- data/bin/fspec +20 -0
- data/bin/fyi +27 -11
- data/bin/ifancy +1 -1
- data/boot/fancy_ext.rb +1 -0
- data/boot/fancy_ext/block_env.rb +1 -9
- data/boot/fancy_ext/delegator.rb +64 -0
- data/boot/fancy_ext/object.rb +4 -0
- data/boot/fancy_ext/thread.rb +4 -0
- data/boot/load.rb +5 -1
- data/boot/rbx-compiler/compiler/ast.rb +0 -1
- data/boot/rbx-compiler/compiler/ast/class_def.rb +2 -0
- data/boot/rbx-compiler/compiler/ast/method_def.rb +2 -0
- data/boot/rbx-compiler/compiler/ast/node.rb +10 -0
- data/boot/rbx-compiler/compiler/ast/ruby_args.rb +12 -0
- data/boot/rbx-compiler/compiler/ast/singleton_method_def.rb +2 -0
- data/boot/rbx-compiler/parser/fancy_parser.bundle +0 -0
- data/boot/rbx-compiler/parser/lexer.lex +5 -11
- data/boot/rbx-compiler/parser/parser.rb +16 -5
- data/boot/rbx-compiler/parser/parser.y +39 -24
- data/doc/api/fancy.css +1 -1
- data/doc/api/fancy.jsonp +1 -1
- data/doc/api/fdoc.js +22 -4
- data/doc/api/index.html +5 -6
- data/doc/api/jquery-ui.min.js +401 -0
- data/doc/api/jquery.tools.min.js +192 -0
- data/doc/api/themeswitchertool.js +250 -0
- data/doc/features.md +17 -0
- data/examples/actor_bunnies.fy +32 -0
- data/examples/actors.fy +26 -0
- data/examples/actors_primitive.fy +27 -0
- data/examples/actors_ring.fy +37 -0
- data/examples/armstrong_numbers.fy +1 -1
- data/examples/array.fy +7 -9
- data/examples/async_send.fy +1 -2
- data/examples/blocks.fy +4 -4
- data/examples/call_with_receiver.fy +1 -1
- data/examples/class.fy +1 -1
- data/examples/default_args.fy +4 -1
- data/examples/define_methods.fy +2 -2
- data/examples/echo.fy +1 -1
- data/examples/factorial.fy +1 -1
- data/examples/future_composition.fy +2 -2
- data/examples/futures.fy +0 -5
- data/examples/game_of_life.fy +1 -1
- data/examples/person.fy +1 -1
- data/lib/argv.fy +7 -2
- data/lib/array.fy +109 -42
- data/lib/block.fy +39 -14
- data/lib/boot.fy +2 -0
- data/lib/class.fy +2 -0
- data/lib/compiler/ast.fy +2 -1
- data/lib/compiler/ast/assign.fy +2 -3
- data/lib/compiler/ast/async_send.fy +1 -15
- data/lib/compiler/ast/class_def.fy +2 -1
- data/lib/compiler/ast/expression_list.fy +4 -5
- data/lib/compiler/ast/future_send.fy +1 -10
- data/lib/compiler/ast/goto.fy +46 -0
- data/lib/compiler/ast/identifier.fy +9 -7
- data/lib/compiler/ast/literals.fy +8 -1
- data/lib/compiler/ast/match.fy +14 -4
- data/lib/compiler/ast/message_send.fy +34 -6
- data/lib/compiler/ast/method_def.fy +6 -6
- data/lib/compiler/ast/node.fy +3 -3
- data/lib/compiler/ast/range.fy +1 -0
- data/lib/compiler/ast/script.fy +0 -2
- data/lib/compiler/ast/singleton_method_def.fy +2 -4
- data/lib/compiler/ast/string_interpolation.fy +17 -0
- data/lib/compiler/ast/super.fy +5 -4
- data/lib/compiler/ast/try_catch.fy +8 -6
- data/lib/compiler/ast/tuple_literal.fy +3 -2
- data/lib/compiler/command.fy +0 -1
- data/lib/compiler/compiler.fy +1 -5
- data/lib/compiler/stages.fy +6 -14
- data/lib/documentation.fy +57 -46
- data/lib/enumerable.fy +257 -23
- data/lib/enumerator.fy +122 -15
- data/lib/false_class.fy +10 -1
- data/lib/fancy_spec.fy +263 -61
- data/lib/fdoc.fy +11 -25
- data/lib/fiber.fy +11 -0
- data/lib/file.fy +8 -11
- data/lib/future.fy +84 -5
- data/lib/hash.fy +65 -14
- data/lib/integer.fy +35 -0
- data/lib/iteration.fy +54 -29
- data/lib/message.fy +6 -0
- data/lib/method.fy +0 -16
- data/lib/nil_class.fy +58 -8
- data/lib/number.fy +49 -22
- data/lib/object.fy +371 -65
- data/lib/package.fy +24 -1
- data/lib/package/installer.fy +5 -9
- data/lib/package/specification.fy +2 -2
- data/lib/parser/ext/lexer.lex +15 -11
- data/lib/parser/ext/parser.y +70 -23
- data/lib/parser/methods.fy +33 -14
- data/lib/proxy.fy +33 -3
- data/lib/range.fy +28 -0
- data/lib/rbx.fy +3 -1
- data/lib/rbx/actor.fy +53 -0
- data/lib/rbx/alpha.fy +31 -0
- data/lib/rbx/array.fy +21 -12
- data/lib/rbx/bignum.fy +6 -2
- data/lib/rbx/block.fy +23 -26
- data/lib/rbx/class.fy +54 -2
- data/lib/rbx/code_loader.fy +8 -4
- data/lib/rbx/date.fy +9 -0
- data/lib/rbx/directory.fy +18 -0
- data/lib/rbx/environment_variables.fy +1 -0
- data/lib/rbx/exception.fy +9 -2
- data/lib/rbx/fiber.fy +22 -4
- data/lib/rbx/file.fy +5 -5
- data/lib/rbx/fixnum.fy +5 -0
- data/lib/rbx/float.fy +11 -3
- data/lib/rbx/hash.fy +31 -16
- data/lib/rbx/integer.fy +1 -0
- data/lib/rbx/io.fy +17 -7
- data/lib/rbx/match_data.fy +15 -4
- data/lib/rbx/method.fy +40 -7
- data/lib/rbx/name_error.fy +4 -0
- data/lib/rbx/object.fy +92 -24
- data/lib/rbx/range.fy +20 -6
- data/lib/rbx/regexp.fy +11 -3
- data/lib/rbx/string.fy +51 -1
- data/lib/rbx/stringio.fy +17 -0
- data/lib/rbx/symbol.fy +15 -1
- data/lib/rbx/system.fy +20 -2
- data/lib/rbx/tcp_server.fy +4 -1
- data/lib/rbx/tcp_socket.fy +11 -0
- data/lib/rbx/time.fy +6 -0
- data/lib/rbx/tuple.fy +14 -5
- data/lib/set.fy +144 -29
- data/lib/stack.fy +42 -11
- data/lib/string.fy +118 -8
- data/lib/struct.fy +13 -3
- data/lib/symbol.fy +21 -2
- data/lib/thread_pool.fy +2 -1
- data/lib/true_class.fy +45 -7
- data/lib/tuple.fy +27 -9
- data/lib/version.fy +2 -2
- data/ruby_lib/fancy +43 -0
- data/ruby_lib/fdoc +23 -0
- data/ruby_lib/fspec +3 -0
- data/ruby_lib/fyi +3 -0
- data/ruby_lib/ifancy +3 -0
- data/tests/argv.fy +5 -9
- data/tests/array.fy +323 -196
- data/tests/assignment.fy +29 -29
- data/tests/block.fy +72 -59
- data/tests/class.fy +227 -138
- data/tests/control_flow.fy +83 -51
- data/tests/documentation.fy +8 -8
- data/tests/enumerable.fy +8 -0
- data/tests/enumerator.fy +47 -29
- data/tests/exception.fy +49 -32
- data/tests/file.fy +28 -28
- data/tests/fixnum.fy +170 -0
- data/tests/future.fy +24 -7
- data/tests/hash.fy +55 -38
- data/tests/method.fy +50 -43
- data/tests/nil_class.fy +37 -37
- data/tests/object.fy +152 -70
- data/tests/pattern_matching.fy +67 -31
- data/tests/range.fy +6 -6
- data/tests/set.fy +101 -4
- data/tests/stack.fy +14 -5
- data/tests/string.fy +115 -61
- data/tests/stringio.fy +18 -0
- data/tests/struct.fy +27 -0
- data/tests/symbol.fy +19 -6
- data/tests/true_class.fy +34 -34
- data/tests/tuple.fy +30 -12
- metadata +103 -81
- data/boot/rbx-compiler/compiler/ast/require.rb +0 -20
- data/examples/actor.fy +0 -37
- data/examples/curl_async.fy +0 -37
- data/lib/compiler/ast/require.fy +0 -15
- data/tests/number.fy +0 -135
- data/tests/parsing/sexp.fy +0 -50
data/lib/enumerable.fy
CHANGED
|
@@ -10,6 +10,7 @@ class FancyEnumerable {
|
|
|
10
10
|
|
|
11
11
|
Indicates, if a collection includes a given element.
|
|
12
12
|
"""
|
|
13
|
+
|
|
13
14
|
any?: |x| { item == x }
|
|
14
15
|
}
|
|
15
16
|
|
|
@@ -26,6 +27,25 @@ class FancyEnumerable {
|
|
|
26
27
|
}
|
|
27
28
|
}
|
|
28
29
|
|
|
30
|
+
def join: str {
|
|
31
|
+
"""
|
|
32
|
+
@str Value (usually a @String@) to be used for the joined @String@.
|
|
33
|
+
@return @String@ containing all elements in @self interspersed with @str.
|
|
34
|
+
|
|
35
|
+
Joins a collection with a @String@ between each element, returning a new @String@.
|
|
36
|
+
|
|
37
|
+
\"hello, world\” join: \"-\" # => \"h-e-l-l-o-,- -w-o-r-l-d\"
|
|
38
|
+
"""
|
|
39
|
+
|
|
40
|
+
s = ""
|
|
41
|
+
each: |c| {
|
|
42
|
+
s << c
|
|
43
|
+
} in_between: {
|
|
44
|
+
s << str
|
|
45
|
+
}
|
|
46
|
+
s
|
|
47
|
+
}
|
|
48
|
+
|
|
29
49
|
def any?: condition {
|
|
30
50
|
"""
|
|
31
51
|
@condition @Block@ (or @Callable) that is used to check if any element in @self yields true for it.
|
|
@@ -57,7 +77,13 @@ class FancyEnumerable {
|
|
|
57
77
|
}
|
|
58
78
|
|
|
59
79
|
def find: item {
|
|
60
|
-
"
|
|
80
|
+
"""
|
|
81
|
+
@item Item to be found in @self.
|
|
82
|
+
@return The first element that is equal to @item or @nil, if none found.
|
|
83
|
+
|
|
84
|
+
Returns @nil, if @item (or anything that returns @true when comparing to @item) isn't found.
|
|
85
|
+
Otherwise returns that element that is equal to @item.
|
|
86
|
+
"""
|
|
61
87
|
|
|
62
88
|
if: (item is_a?: Block) then: {
|
|
63
89
|
find_by: item
|
|
@@ -85,7 +111,12 @@ class FancyEnumerable {
|
|
|
85
111
|
}
|
|
86
112
|
|
|
87
113
|
def map: block {
|
|
88
|
-
"
|
|
114
|
+
"""
|
|
115
|
+
@block A @Block@ that gets called with each element in @self.
|
|
116
|
+
@return An @Array@ containing all values of calling @block with each element in @self.
|
|
117
|
+
|
|
118
|
+
Returns a new @Array@ with the results of calling a given block for every element.
|
|
119
|
+
"""
|
|
89
120
|
|
|
90
121
|
coll = []
|
|
91
122
|
each: |x| {
|
|
@@ -95,7 +126,12 @@ class FancyEnumerable {
|
|
|
95
126
|
}
|
|
96
127
|
|
|
97
128
|
def select: condition {
|
|
98
|
-
"
|
|
129
|
+
"""
|
|
130
|
+
@condition A @Block@ that is used as a filter on all elements in @self.
|
|
131
|
+
@return An @Array@ containing all elements in @self that yield @true when called with @condition.
|
|
132
|
+
|
|
133
|
+
Returns a new @Array@ with all elements that meet the given condition block.
|
|
134
|
+
"""
|
|
99
135
|
|
|
100
136
|
coll = []
|
|
101
137
|
each: |x| {
|
|
@@ -105,7 +141,10 @@ class FancyEnumerable {
|
|
|
105
141
|
}
|
|
106
142
|
|
|
107
143
|
def reject: condition {
|
|
108
|
-
"
|
|
144
|
+
"""
|
|
145
|
+
Similar to @select:@ but inverse.
|
|
146
|
+
Returns a new @Array@ with all elements that don't meet the given condition block.
|
|
147
|
+
"""
|
|
109
148
|
|
|
110
149
|
coll = []
|
|
111
150
|
each: |x| {
|
|
@@ -115,7 +154,17 @@ class FancyEnumerable {
|
|
|
115
154
|
}
|
|
116
155
|
|
|
117
156
|
def take_while: condition {
|
|
118
|
-
"
|
|
157
|
+
"""
|
|
158
|
+
@condition A @Block@ that is used as a condition for filtering.
|
|
159
|
+
@return An @Array@ of all elements from the beginning until @condition yields @false.
|
|
160
|
+
|
|
161
|
+
Returns a new @Array@ by taking elements from the beginning
|
|
162
|
+
as long as they meet the given condition block.
|
|
163
|
+
|
|
164
|
+
Example:
|
|
165
|
+
[1,2,3,4,5] take_while: |x| { x < 4 } # => [1,2,3]
|
|
166
|
+
"""
|
|
167
|
+
|
|
119
168
|
coll = []
|
|
120
169
|
each: |x| {
|
|
121
170
|
if: (condition call: [x]) then: {
|
|
@@ -128,7 +177,14 @@ class FancyEnumerable {
|
|
|
128
177
|
}
|
|
129
178
|
|
|
130
179
|
def drop_while: condition {
|
|
131
|
-
"
|
|
180
|
+
"""
|
|
181
|
+
Similar to @take_while:@ but inverse.
|
|
182
|
+
Returns a new @Array@ by skipping elements from the beginning
|
|
183
|
+
as long as they meet the given condition block.
|
|
184
|
+
|
|
185
|
+
Example:
|
|
186
|
+
[1,2,3,4,5] drop_while: |x| { x < 4 } # => [4,5]
|
|
187
|
+
"""
|
|
132
188
|
|
|
133
189
|
coll = []
|
|
134
190
|
drop = nil
|
|
@@ -137,7 +193,7 @@ class FancyEnumerable {
|
|
|
137
193
|
if: (drop or: first_check) then: {
|
|
138
194
|
drop = condition call: [x]
|
|
139
195
|
first_check = nil
|
|
140
|
-
# check, if we actually have to insert
|
|
196
|
+
# check, if we actually have to insert this one:
|
|
141
197
|
unless: drop do: {
|
|
142
198
|
coll << x
|
|
143
199
|
}
|
|
@@ -149,6 +205,14 @@ class FancyEnumerable {
|
|
|
149
205
|
}
|
|
150
206
|
|
|
151
207
|
def take: amount {
|
|
208
|
+
"""
|
|
209
|
+
@amount Amount of elements to take from @self.
|
|
210
|
+
@return First @amount elements of @self in an @Array@.
|
|
211
|
+
|
|
212
|
+
Example:
|
|
213
|
+
[1,2,3,4] take: 2 # => [1,2]
|
|
214
|
+
"""
|
|
215
|
+
|
|
152
216
|
i = 0
|
|
153
217
|
take_while: {
|
|
154
218
|
i = i + 1
|
|
@@ -157,6 +221,14 @@ class FancyEnumerable {
|
|
|
157
221
|
}
|
|
158
222
|
|
|
159
223
|
def drop: amount {
|
|
224
|
+
"""
|
|
225
|
+
@amount Amount of elements to skip in @self.
|
|
226
|
+
@return An @Array@ of all but the first @amount elements in @self.
|
|
227
|
+
|
|
228
|
+
Example:
|
|
229
|
+
[1,2,3,4,5] drop: 2 # => [3,4,5]
|
|
230
|
+
"""
|
|
231
|
+
|
|
160
232
|
i = 0
|
|
161
233
|
drop_while: {
|
|
162
234
|
i = i + 1
|
|
@@ -165,7 +237,13 @@ class FancyEnumerable {
|
|
|
165
237
|
}
|
|
166
238
|
|
|
167
239
|
def reduce: block init_val: init_val {
|
|
168
|
-
"
|
|
240
|
+
"""
|
|
241
|
+
Calculates a value based on a given block to be called on an accumulator
|
|
242
|
+
value and an initial value.
|
|
243
|
+
|
|
244
|
+
Example:
|
|
245
|
+
[1,2,3] reduce: |sum val| { sum + val } init_val: 0 # => 6
|
|
246
|
+
"""
|
|
169
247
|
|
|
170
248
|
acc = init_val
|
|
171
249
|
each: |x| {
|
|
@@ -176,13 +254,25 @@ class FancyEnumerable {
|
|
|
176
254
|
|
|
177
255
|
def inject: val into: block {
|
|
178
256
|
"""
|
|
179
|
-
Same as reduce:init_val: but taking the initial value as first
|
|
257
|
+
Same as reduce:init_val: but taking the initial value as first
|
|
258
|
+
and the reducing block as second parameter.
|
|
259
|
+
|
|
260
|
+
Example:
|
|
261
|
+
[1,2,3] inject: 0 into: |sum val| { sum + val } # => 6
|
|
180
262
|
"""
|
|
263
|
+
|
|
181
264
|
reduce: block init_val: val
|
|
182
265
|
}
|
|
183
266
|
|
|
184
267
|
def uniq {
|
|
185
|
-
"
|
|
268
|
+
"""
|
|
269
|
+
@return @Array@ of all unique elements in @self.
|
|
270
|
+
|
|
271
|
+
Returns a new Array with all unique values (double entries are skipped).
|
|
272
|
+
|
|
273
|
+
Example:
|
|
274
|
+
[1,2,1,2,3] uniq # => [1,2,3]
|
|
275
|
+
"""
|
|
186
276
|
|
|
187
277
|
uniq_vals = []
|
|
188
278
|
each: |x| {
|
|
@@ -194,7 +284,11 @@ class FancyEnumerable {
|
|
|
194
284
|
}
|
|
195
285
|
|
|
196
286
|
def size {
|
|
197
|
-
"
|
|
287
|
+
"""
|
|
288
|
+
@return Amount of elements in @self.
|
|
289
|
+
|
|
290
|
+
Returns the size of an Enumerable.
|
|
291
|
+
"""
|
|
198
292
|
|
|
199
293
|
i = 0
|
|
200
294
|
each: |x| {
|
|
@@ -204,18 +298,32 @@ class FancyEnumerable {
|
|
|
204
298
|
}
|
|
205
299
|
|
|
206
300
|
def empty? {
|
|
207
|
-
"
|
|
301
|
+
"""
|
|
302
|
+
@return @true, if size of @self is 0, @false otherwise.
|
|
303
|
+
|
|
304
|
+
Indicates, if the Enumerable is empty (has no elements).
|
|
305
|
+
"""
|
|
306
|
+
|
|
208
307
|
size == 0
|
|
209
308
|
}
|
|
210
309
|
|
|
211
310
|
def first {
|
|
311
|
+
"""
|
|
312
|
+
@return First element in @self or @nil, if empty.
|
|
313
|
+
"""
|
|
314
|
+
|
|
212
315
|
each: |x| {
|
|
213
316
|
return x
|
|
214
317
|
}
|
|
318
|
+
nil
|
|
215
319
|
}
|
|
216
320
|
|
|
217
321
|
def last {
|
|
218
|
-
"
|
|
322
|
+
"""
|
|
323
|
+
@return Last element in @self or @nil, if empty.
|
|
324
|
+
|
|
325
|
+
Returns the last element in an Enumerable.
|
|
326
|
+
"""
|
|
219
327
|
|
|
220
328
|
item = nil
|
|
221
329
|
each: |x| {
|
|
@@ -225,34 +333,105 @@ class FancyEnumerable {
|
|
|
225
333
|
}
|
|
226
334
|
|
|
227
335
|
def compact {
|
|
228
|
-
"
|
|
336
|
+
"""
|
|
337
|
+
@return @Array@ with all non-nil elements in @self.
|
|
338
|
+
|
|
339
|
+
Returns a new @Array@ with all values removed that are @nil ( return @true on @nil? ).
|
|
340
|
+
|
|
341
|
+
Example:
|
|
342
|
+
[1,2,nil,3,nil] compact # => [1,2,3]
|
|
343
|
+
"""
|
|
229
344
|
|
|
230
345
|
reject: |x| { x nil? }
|
|
231
346
|
}
|
|
232
347
|
|
|
233
|
-
def superior_by: comparison_block {
|
|
234
|
-
"
|
|
348
|
+
def superior_by: comparison_block taking: selection_block ('identity) {
|
|
349
|
+
"""
|
|
350
|
+
@comparison_block @Block@ to be used for comparison.
|
|
351
|
+
@selection_block @Block@ to be used for selecting the values to be used for comparison by @comparison_bock.
|
|
352
|
+
@return Superior element in @self in terms of @comparison_block.
|
|
353
|
+
|
|
354
|
+
Returns the superior element in the @Enumerable that has met
|
|
355
|
+
the given comparison block with all other elements,
|
|
356
|
+
applied to whatever @selection_block returns for each element.
|
|
357
|
+
@selection_block defaults to @identity.
|
|
358
|
+
|
|
359
|
+
Examples:
|
|
360
|
+
[1,2,5,3,4] superior_by: '> # => 5
|
|
361
|
+
[1,2,5,3,4] superior_by: '< # => 1
|
|
362
|
+
[[1,2], [2,3,4], [], [1]] superior_by: '> taking: 'size # => [2,3,4]
|
|
363
|
+
[[1,2], [2,3,4], [-1]] superior_by: '< taking: 'first # => [-1]
|
|
364
|
+
"""
|
|
365
|
+
|
|
235
366
|
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
367
|
+
pairs = self map: |val| {
|
|
368
|
+
(val, selection_block call: [val])
|
|
369
|
+
}
|
|
370
|
+
|
|
371
|
+
retval = pairs first
|
|
372
|
+
pairs each: |p| {
|
|
373
|
+
if: (comparison_block call: [p second, retval second]) then: {
|
|
374
|
+
retval = p
|
|
240
375
|
}
|
|
241
376
|
}
|
|
242
|
-
retval
|
|
377
|
+
retval first
|
|
243
378
|
}
|
|
244
379
|
|
|
245
380
|
def max {
|
|
246
|
-
"
|
|
381
|
+
"""
|
|
382
|
+
@return Maximum value in @self.
|
|
383
|
+
|
|
384
|
+
Returns the maximum value in the Enumerable (via the '>' comparison message).
|
|
385
|
+
"""
|
|
386
|
+
|
|
247
387
|
superior_by: '>
|
|
248
388
|
}
|
|
249
389
|
|
|
250
390
|
def min {
|
|
251
|
-
"
|
|
391
|
+
"""
|
|
392
|
+
@return Minimum value in @self.
|
|
393
|
+
|
|
394
|
+
Returns the minimum value in the Enumerable (via the '<' comparison message).
|
|
395
|
+
"""
|
|
396
|
+
|
|
252
397
|
superior_by: '<
|
|
253
398
|
}
|
|
254
399
|
|
|
400
|
+
def sum {
|
|
401
|
+
"""
|
|
402
|
+
Calculates the sum of all the elements in the @Enumerable
|
|
403
|
+
(assuming them to be @Number@s (implementing '+' & '*')).
|
|
404
|
+
"""
|
|
405
|
+
|
|
406
|
+
reduce: '+ init_val: 0
|
|
407
|
+
}
|
|
408
|
+
|
|
409
|
+
def product {
|
|
410
|
+
"""
|
|
411
|
+
Calculates the product of all the elements in the @Enumerable
|
|
412
|
+
(assuming them to be @Number@s (implementing @+ & @*)).
|
|
413
|
+
"""
|
|
414
|
+
|
|
415
|
+
reduce: '* init_val: 1
|
|
416
|
+
}
|
|
417
|
+
|
|
418
|
+
def average {
|
|
419
|
+
"""
|
|
420
|
+
@return Average value in @self (expecting @Number@s or Objects implementing @+ and @*).
|
|
421
|
+
"""
|
|
422
|
+
|
|
423
|
+
{ return 0 } if: (size == 0)
|
|
424
|
+
sum to_f / size
|
|
425
|
+
}
|
|
426
|
+
|
|
255
427
|
def partition_by: block {
|
|
428
|
+
"""
|
|
429
|
+
@block @Block@ that gets used to decide when to partition elements in @self.
|
|
430
|
+
@return @Array@ of @Array@s, partitioned by equal return values of calling @block with each element
|
|
431
|
+
|
|
432
|
+
Example:
|
|
433
|
+
0 upto: 10 . partition_by: @{< 3} # => [[0, 1, 2], [3, 4, 5, 6, 7, 8, 9, 10]]
|
|
434
|
+
"""
|
|
256
435
|
last = block call: [first]
|
|
257
436
|
coll = []
|
|
258
437
|
tmp_coll = []
|
|
@@ -269,4 +448,59 @@ class FancyEnumerable {
|
|
|
269
448
|
coll << tmp_coll
|
|
270
449
|
coll
|
|
271
450
|
}
|
|
451
|
+
|
|
452
|
+
def random {
|
|
453
|
+
"""
|
|
454
|
+
@return Random element in @self.
|
|
455
|
+
"""
|
|
456
|
+
|
|
457
|
+
at: (rand(size))
|
|
458
|
+
}
|
|
459
|
+
|
|
460
|
+
def sort_by: block {
|
|
461
|
+
"""
|
|
462
|
+
@block @Block@ taking 2 arguments used to compare elements in a collection.
|
|
463
|
+
@return Sorted @Array@ of elements in @self.
|
|
464
|
+
|
|
465
|
+
Sorts a collection by a given comparison block.
|
|
466
|
+
"""
|
|
467
|
+
|
|
468
|
+
if: (block is_a?: Symbol) then: {
|
|
469
|
+
sort() |a b| {
|
|
470
|
+
a receive_message: block . <=> (b receive_message: block)
|
|
471
|
+
}
|
|
472
|
+
} else: {
|
|
473
|
+
sort(&block)
|
|
474
|
+
}
|
|
475
|
+
}
|
|
476
|
+
|
|
477
|
+
def in_groups_of: size {
|
|
478
|
+
"""
|
|
479
|
+
@size Maximum size of each group.
|
|
480
|
+
@return @Array@ of @Array@s with a max size of @size (grouped).
|
|
481
|
+
|
|
482
|
+
Example usage:
|
|
483
|
+
[1,2,3,4,5] in_groups_of: 3 # => [[1,2,3],[4,5]]
|
|
484
|
+
"""
|
|
485
|
+
|
|
486
|
+
groups = []
|
|
487
|
+
tmp = []
|
|
488
|
+
enum = to_enum
|
|
489
|
+
|
|
490
|
+
loop: {
|
|
491
|
+
size times: {
|
|
492
|
+
tmp << (enum next)
|
|
493
|
+
}
|
|
494
|
+
|
|
495
|
+
if: (enum ended?) then: {
|
|
496
|
+
{ groups << tmp } unless: $ tmp empty?
|
|
497
|
+
break
|
|
498
|
+
}
|
|
499
|
+
|
|
500
|
+
groups << tmp
|
|
501
|
+
tmp = []
|
|
502
|
+
}
|
|
503
|
+
|
|
504
|
+
groups
|
|
505
|
+
}
|
|
272
506
|
}
|
data/lib/enumerator.fy
CHANGED
|
@@ -1,14 +1,44 @@
|
|
|
1
1
|
class FancyEnumerator {
|
|
2
|
-
def initialize: @
|
|
2
|
+
def initialize: @collection {
|
|
3
|
+
"""
|
|
4
|
+
@collection Collection to iterate over.
|
|
5
|
+
|
|
6
|
+
Initializes a new FancyEnumerator with a given @collection,
|
|
7
|
+
using #each: for iteration.
|
|
8
|
+
"""
|
|
9
|
+
|
|
3
10
|
@iterator = 'each:
|
|
4
11
|
rewind
|
|
5
12
|
}
|
|
6
13
|
|
|
7
|
-
def initialize: @
|
|
14
|
+
def initialize: @collection with: @iterator {
|
|
15
|
+
"""
|
|
16
|
+
@collection Collection to iterate over.
|
|
17
|
+
@iterator Selector to use to iterate over @collection.
|
|
18
|
+
|
|
19
|
+
Initializes a new FancyEnumerator with a given @collection
|
|
20
|
+
and @iterator selector to be used for iteration.
|
|
21
|
+
"""
|
|
22
|
+
|
|
8
23
|
rewind
|
|
9
24
|
}
|
|
10
25
|
|
|
11
26
|
def next {
|
|
27
|
+
"""
|
|
28
|
+
@return Next element in the collection this enumerator is attached to.
|
|
29
|
+
|
|
30
|
+
Returns the next element in the collection this enumerator is attached to.
|
|
31
|
+
It will move the internal position forward (compared to e.g. #peek, which doesn't).
|
|
32
|
+
|
|
33
|
+
Example:
|
|
34
|
+
a = [1,2,3]
|
|
35
|
+
e = a to_enum
|
|
36
|
+
e next # => 1
|
|
37
|
+
e next # => 2
|
|
38
|
+
e next # => 3
|
|
39
|
+
e next # => raises Fancy StopIteration
|
|
40
|
+
"""
|
|
41
|
+
|
|
12
42
|
if: @peeked then: {
|
|
13
43
|
@peeked = false
|
|
14
44
|
@peek
|
|
@@ -22,6 +52,16 @@ class FancyEnumerator {
|
|
|
22
52
|
}
|
|
23
53
|
}
|
|
24
54
|
|
|
55
|
+
def ended? {
|
|
56
|
+
"""
|
|
57
|
+
@return @true if the enumerator has ended (no more values left), @false otherwise.
|
|
58
|
+
|
|
59
|
+
Indicates if an enumerator has ended (no more values left).
|
|
60
|
+
"""
|
|
61
|
+
|
|
62
|
+
@fiber alive? not
|
|
63
|
+
}
|
|
64
|
+
|
|
25
65
|
def peek {
|
|
26
66
|
"""
|
|
27
67
|
Returns the next object in the FancyEnumerator, but doesn't move the
|
|
@@ -29,15 +69,16 @@ class FancyEnumerator {
|
|
|
29
69
|
When the position reaches the end, a Fancy StopIteration exception is
|
|
30
70
|
raised.
|
|
31
71
|
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
72
|
+
Example:
|
|
73
|
+
a = [1,2,3]
|
|
74
|
+
e = a to_enum
|
|
75
|
+
e next p #=> 1
|
|
76
|
+
e peek p #=> 2
|
|
77
|
+
e peek p #=> 2
|
|
78
|
+
e peek p #=> 2
|
|
79
|
+
e next p #=> 2
|
|
80
|
+
e next p #=> 3
|
|
81
|
+
e next p #=> raises Fancy StopIteration
|
|
41
82
|
"""
|
|
42
83
|
|
|
43
84
|
unless: @peeked do: {
|
|
@@ -54,24 +95,90 @@ class FancyEnumerator {
|
|
|
54
95
|
}
|
|
55
96
|
|
|
56
97
|
def rewind {
|
|
98
|
+
"""
|
|
99
|
+
Resets the enumerator to start from the collection's beginning.
|
|
100
|
+
"""
|
|
101
|
+
|
|
57
102
|
@peeked = false
|
|
58
103
|
@peek = nil
|
|
59
104
|
|
|
60
105
|
@fiber = Fiber new: {
|
|
61
106
|
param = |element| { yield: element }
|
|
62
|
-
@
|
|
107
|
+
@collection receive_message: @iterator with_params: [param]
|
|
63
108
|
}
|
|
64
109
|
}
|
|
65
110
|
|
|
66
111
|
def with: object each: block {
|
|
112
|
+
"""
|
|
113
|
+
@object Object to pass along to @block with each element in the collection.
|
|
114
|
+
@block A @Block@ to be called with each element in the collection and @object.
|
|
115
|
+
|
|
116
|
+
Similar to #each: but also passing in a given @object to each invocation of @block.
|
|
117
|
+
"""
|
|
118
|
+
|
|
119
|
+
each: |element| {
|
|
120
|
+
block call: [element, object]
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
return object
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
def each: block {
|
|
127
|
+
"""
|
|
128
|
+
@block @Block@ to be called with each element in the collection (iteration).
|
|
129
|
+
|
|
130
|
+
Calls a given @Block@ with each element in the collection this enumerator is attached to.
|
|
131
|
+
Used for iterating over the collection using this enumerator.
|
|
132
|
+
"""
|
|
133
|
+
|
|
67
134
|
loop: {
|
|
68
135
|
try {
|
|
69
|
-
block call: [next
|
|
136
|
+
block call: [next]
|
|
70
137
|
} catch (Fancy StopIteration) => ex {
|
|
71
|
-
return
|
|
138
|
+
return self
|
|
72
139
|
}
|
|
73
140
|
}
|
|
141
|
+
}
|
|
74
142
|
|
|
75
|
-
|
|
143
|
+
def chunk: block {
|
|
144
|
+
Generator new: |inner_block| {
|
|
145
|
+
enums = []
|
|
146
|
+
last = nil
|
|
147
|
+
previous = nil
|
|
148
|
+
stack = []
|
|
149
|
+
|
|
150
|
+
each: |element| {
|
|
151
|
+
result = (block call: [element]) not not
|
|
152
|
+
if: (previous == result) then: {
|
|
153
|
+
stack << element
|
|
154
|
+
} else: {
|
|
155
|
+
previous if_nil: {
|
|
156
|
+
# wait one gap to call
|
|
157
|
+
} else: {
|
|
158
|
+
inner_block call: [[previous, stack]]
|
|
159
|
+
}
|
|
160
|
+
previous = result
|
|
161
|
+
stack = [element]
|
|
162
|
+
last = [result, stack]
|
|
163
|
+
enums << last
|
|
164
|
+
}
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
self
|
|
168
|
+
} . to_enum
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
class Generator {
|
|
172
|
+
def initialize: @block {}
|
|
173
|
+
|
|
174
|
+
def each: block {
|
|
175
|
+
@block call: [block]
|
|
176
|
+
}
|
|
177
|
+
}
|
|
178
|
+
|
|
179
|
+
def to_a {
|
|
180
|
+
output = []
|
|
181
|
+
each: |element| { output << element }
|
|
182
|
+
output
|
|
76
183
|
}
|
|
77
184
|
}
|