fancy 0.3.3 → 0.4.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (182) hide show
  1. data/README.md +14 -14
  2. data/Rakefile +16 -4
  3. data/bin/fancy +3 -0
  4. data/bin/fspec +20 -0
  5. data/bin/fyi +27 -11
  6. data/bin/ifancy +1 -1
  7. data/boot/fancy_ext.rb +1 -0
  8. data/boot/fancy_ext/block_env.rb +1 -9
  9. data/boot/fancy_ext/delegator.rb +64 -0
  10. data/boot/fancy_ext/object.rb +4 -0
  11. data/boot/fancy_ext/thread.rb +4 -0
  12. data/boot/load.rb +5 -1
  13. data/boot/rbx-compiler/compiler/ast.rb +0 -1
  14. data/boot/rbx-compiler/compiler/ast/class_def.rb +2 -0
  15. data/boot/rbx-compiler/compiler/ast/method_def.rb +2 -0
  16. data/boot/rbx-compiler/compiler/ast/node.rb +10 -0
  17. data/boot/rbx-compiler/compiler/ast/ruby_args.rb +12 -0
  18. data/boot/rbx-compiler/compiler/ast/singleton_method_def.rb +2 -0
  19. data/boot/rbx-compiler/parser/fancy_parser.bundle +0 -0
  20. data/boot/rbx-compiler/parser/lexer.lex +5 -11
  21. data/boot/rbx-compiler/parser/parser.rb +16 -5
  22. data/boot/rbx-compiler/parser/parser.y +39 -24
  23. data/doc/api/fancy.css +1 -1
  24. data/doc/api/fancy.jsonp +1 -1
  25. data/doc/api/fdoc.js +22 -4
  26. data/doc/api/index.html +5 -6
  27. data/doc/api/jquery-ui.min.js +401 -0
  28. data/doc/api/jquery.tools.min.js +192 -0
  29. data/doc/api/themeswitchertool.js +250 -0
  30. data/doc/features.md +17 -0
  31. data/examples/actor_bunnies.fy +32 -0
  32. data/examples/actors.fy +26 -0
  33. data/examples/actors_primitive.fy +27 -0
  34. data/examples/actors_ring.fy +37 -0
  35. data/examples/armstrong_numbers.fy +1 -1
  36. data/examples/array.fy +7 -9
  37. data/examples/async_send.fy +1 -2
  38. data/examples/blocks.fy +4 -4
  39. data/examples/call_with_receiver.fy +1 -1
  40. data/examples/class.fy +1 -1
  41. data/examples/default_args.fy +4 -1
  42. data/examples/define_methods.fy +2 -2
  43. data/examples/echo.fy +1 -1
  44. data/examples/factorial.fy +1 -1
  45. data/examples/future_composition.fy +2 -2
  46. data/examples/futures.fy +0 -5
  47. data/examples/game_of_life.fy +1 -1
  48. data/examples/person.fy +1 -1
  49. data/lib/argv.fy +7 -2
  50. data/lib/array.fy +109 -42
  51. data/lib/block.fy +39 -14
  52. data/lib/boot.fy +2 -0
  53. data/lib/class.fy +2 -0
  54. data/lib/compiler/ast.fy +2 -1
  55. data/lib/compiler/ast/assign.fy +2 -3
  56. data/lib/compiler/ast/async_send.fy +1 -15
  57. data/lib/compiler/ast/class_def.fy +2 -1
  58. data/lib/compiler/ast/expression_list.fy +4 -5
  59. data/lib/compiler/ast/future_send.fy +1 -10
  60. data/lib/compiler/ast/goto.fy +46 -0
  61. data/lib/compiler/ast/identifier.fy +9 -7
  62. data/lib/compiler/ast/literals.fy +8 -1
  63. data/lib/compiler/ast/match.fy +14 -4
  64. data/lib/compiler/ast/message_send.fy +34 -6
  65. data/lib/compiler/ast/method_def.fy +6 -6
  66. data/lib/compiler/ast/node.fy +3 -3
  67. data/lib/compiler/ast/range.fy +1 -0
  68. data/lib/compiler/ast/script.fy +0 -2
  69. data/lib/compiler/ast/singleton_method_def.fy +2 -4
  70. data/lib/compiler/ast/string_interpolation.fy +17 -0
  71. data/lib/compiler/ast/super.fy +5 -4
  72. data/lib/compiler/ast/try_catch.fy +8 -6
  73. data/lib/compiler/ast/tuple_literal.fy +3 -2
  74. data/lib/compiler/command.fy +0 -1
  75. data/lib/compiler/compiler.fy +1 -5
  76. data/lib/compiler/stages.fy +6 -14
  77. data/lib/documentation.fy +57 -46
  78. data/lib/enumerable.fy +257 -23
  79. data/lib/enumerator.fy +122 -15
  80. data/lib/false_class.fy +10 -1
  81. data/lib/fancy_spec.fy +263 -61
  82. data/lib/fdoc.fy +11 -25
  83. data/lib/fiber.fy +11 -0
  84. data/lib/file.fy +8 -11
  85. data/lib/future.fy +84 -5
  86. data/lib/hash.fy +65 -14
  87. data/lib/integer.fy +35 -0
  88. data/lib/iteration.fy +54 -29
  89. data/lib/message.fy +6 -0
  90. data/lib/method.fy +0 -16
  91. data/lib/nil_class.fy +58 -8
  92. data/lib/number.fy +49 -22
  93. data/lib/object.fy +371 -65
  94. data/lib/package.fy +24 -1
  95. data/lib/package/installer.fy +5 -9
  96. data/lib/package/specification.fy +2 -2
  97. data/lib/parser/ext/lexer.lex +15 -11
  98. data/lib/parser/ext/parser.y +70 -23
  99. data/lib/parser/methods.fy +33 -14
  100. data/lib/proxy.fy +33 -3
  101. data/lib/range.fy +28 -0
  102. data/lib/rbx.fy +3 -1
  103. data/lib/rbx/actor.fy +53 -0
  104. data/lib/rbx/alpha.fy +31 -0
  105. data/lib/rbx/array.fy +21 -12
  106. data/lib/rbx/bignum.fy +6 -2
  107. data/lib/rbx/block.fy +23 -26
  108. data/lib/rbx/class.fy +54 -2
  109. data/lib/rbx/code_loader.fy +8 -4
  110. data/lib/rbx/date.fy +9 -0
  111. data/lib/rbx/directory.fy +18 -0
  112. data/lib/rbx/environment_variables.fy +1 -0
  113. data/lib/rbx/exception.fy +9 -2
  114. data/lib/rbx/fiber.fy +22 -4
  115. data/lib/rbx/file.fy +5 -5
  116. data/lib/rbx/fixnum.fy +5 -0
  117. data/lib/rbx/float.fy +11 -3
  118. data/lib/rbx/hash.fy +31 -16
  119. data/lib/rbx/integer.fy +1 -0
  120. data/lib/rbx/io.fy +17 -7
  121. data/lib/rbx/match_data.fy +15 -4
  122. data/lib/rbx/method.fy +40 -7
  123. data/lib/rbx/name_error.fy +4 -0
  124. data/lib/rbx/object.fy +92 -24
  125. data/lib/rbx/range.fy +20 -6
  126. data/lib/rbx/regexp.fy +11 -3
  127. data/lib/rbx/string.fy +51 -1
  128. data/lib/rbx/stringio.fy +17 -0
  129. data/lib/rbx/symbol.fy +15 -1
  130. data/lib/rbx/system.fy +20 -2
  131. data/lib/rbx/tcp_server.fy +4 -1
  132. data/lib/rbx/tcp_socket.fy +11 -0
  133. data/lib/rbx/time.fy +6 -0
  134. data/lib/rbx/tuple.fy +14 -5
  135. data/lib/set.fy +144 -29
  136. data/lib/stack.fy +42 -11
  137. data/lib/string.fy +118 -8
  138. data/lib/struct.fy +13 -3
  139. data/lib/symbol.fy +21 -2
  140. data/lib/thread_pool.fy +2 -1
  141. data/lib/true_class.fy +45 -7
  142. data/lib/tuple.fy +27 -9
  143. data/lib/version.fy +2 -2
  144. data/ruby_lib/fancy +43 -0
  145. data/ruby_lib/fdoc +23 -0
  146. data/ruby_lib/fspec +3 -0
  147. data/ruby_lib/fyi +3 -0
  148. data/ruby_lib/ifancy +3 -0
  149. data/tests/argv.fy +5 -9
  150. data/tests/array.fy +323 -196
  151. data/tests/assignment.fy +29 -29
  152. data/tests/block.fy +72 -59
  153. data/tests/class.fy +227 -138
  154. data/tests/control_flow.fy +83 -51
  155. data/tests/documentation.fy +8 -8
  156. data/tests/enumerable.fy +8 -0
  157. data/tests/enumerator.fy +47 -29
  158. data/tests/exception.fy +49 -32
  159. data/tests/file.fy +28 -28
  160. data/tests/fixnum.fy +170 -0
  161. data/tests/future.fy +24 -7
  162. data/tests/hash.fy +55 -38
  163. data/tests/method.fy +50 -43
  164. data/tests/nil_class.fy +37 -37
  165. data/tests/object.fy +152 -70
  166. data/tests/pattern_matching.fy +67 -31
  167. data/tests/range.fy +6 -6
  168. data/tests/set.fy +101 -4
  169. data/tests/stack.fy +14 -5
  170. data/tests/string.fy +115 -61
  171. data/tests/stringio.fy +18 -0
  172. data/tests/struct.fy +27 -0
  173. data/tests/symbol.fy +19 -6
  174. data/tests/true_class.fy +34 -34
  175. data/tests/tuple.fy +30 -12
  176. metadata +103 -81
  177. data/boot/rbx-compiler/compiler/ast/require.rb +0 -20
  178. data/examples/actor.fy +0 -37
  179. data/examples/curl_async.fy +0 -37
  180. data/lib/compiler/ast/require.fy +0 -15
  181. data/tests/number.fy +0 -135
  182. data/tests/parsing/sexp.fy +0 -50
@@ -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
- "Returns @nil, if the given object isn't found, or the object, if it is found."
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
- "Returns a new @Array@ with the results of calling a given block for every element"
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
- "Returns a new @Array@ with all elements that meet the given condition block."
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
- "Returns a new @Array@ with all elements that don't meet the given condition block."
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
- "Returns a new @Array@ by taking elements from the beginning as long as they meet the given condition block."
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
- "Returns a new @Array@ by skipping elements from the beginning as long as they meet the given condition block."
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 his one:
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
- "Calculates a value based on a given block to be called on an accumulator value and an initial value."
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 and the reducing block as second parameter.
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
- "Returns a new Array with all unique values (double entries are skipped)."
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
- "Returns the size of an Enumerable."
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
- "Indicates, if the Enumerable is empty (has no elements)."
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
- "Returns the last element in an Enumerable."
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
- "Returns a new @Array@ with all values removed that are @nil ( return @true on @nil? )."
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
- "Returns the superiour element in the @Enumerable that has met the given comparison block with all other elements."
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
- retval = first
237
- each: |x| {
238
- if: (comparison_block call: [x, retval]) then: {
239
- retval = x
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
- "Returns the maximum value in the Enumerable (via the '>' comparison message)."
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
- "Returns the minimum value in the Enumerable (via the '<' comparison message)."
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
  }
@@ -1,14 +1,44 @@
1
1
  class FancyEnumerator {
2
- def initialize: @object {
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: @object with: @iterator {
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
- a = [1,2,3]
33
- e = a to_enum
34
- e next p #=> 1
35
- e peek p #=> 2
36
- e peek p #=> 2
37
- e peek p #=> 2
38
- e next p #=> 2
39
- e next p #=> 3
40
- e next p #=> raises Fancy StopIteration
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
- @object send_message: @iterator with_params: [param]
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, object]
136
+ block call: [next]
70
137
  } catch (Fancy StopIteration) => ex {
71
- return object
138
+ return self
72
139
  }
73
140
  }
141
+ }
74
142
 
75
- return object
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
  }