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