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.
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
  }