fancy 0.5.0 → 0.6.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 (111) hide show
  1. data/AUTHORS +2 -0
  2. data/README.md +6 -1
  3. data/bin/fancy +6 -0
  4. data/bin/ifancy +44 -3
  5. data/boot/fancy_ext/module.rb +4 -0
  6. data/boot/fancy_ext/object.rb +4 -0
  7. data/boot/rbx-compiler/compiler/ast/block.rb +29 -1
  8. data/boot/rbx-compiler/compiler/ast/identifier.rb +6 -0
  9. data/boot/rbx-compiler/compiler/ast/message_send.rb +1 -0
  10. data/boot/rbx-compiler/parser/fancy_parser.bundle +0 -0
  11. data/boot/rbx-compiler/parser/lexer.lex +2 -0
  12. data/boot/rbx-compiler/parser/parser.rb +6 -0
  13. data/boot/rbx-compiler/parser/parser.y +14 -1
  14. data/doc/api/fancy.jsonp +1 -1
  15. data/doc/features.md +24 -0
  16. data/examples/99bottles.fy +5 -0
  17. data/examples/conditions_exceptions.fy +9 -0
  18. data/examples/conditions_parsing.fy +68 -0
  19. data/examples/greeter.fy +9 -0
  20. data/examples/html_generator.fy +59 -29
  21. data/examples/webserver/webserver.fy +8 -11
  22. data/lib/argv.fy +6 -0
  23. data/lib/array.fy +17 -35
  24. data/lib/block.fy +82 -1
  25. data/lib/boot.fy +4 -2
  26. data/lib/compiler.fy +2 -2
  27. data/lib/compiler/ast/block.fy +24 -20
  28. data/lib/compiler/ast/message_send.fy +11 -0
  29. data/lib/contracts.fy +60 -0
  30. data/lib/dynamic_slot_object.fy +61 -0
  31. data/lib/enumerable.fy +432 -394
  32. data/lib/enumerator.fy +152 -150
  33. data/lib/fdoc.fy +4 -17
  34. data/lib/fiber.fy +4 -10
  35. data/lib/file.fy +33 -25
  36. data/lib/future.fy +59 -5
  37. data/lib/hash.fy +54 -1
  38. data/lib/html.fy +107 -0
  39. data/lib/kvo.fy +173 -0
  40. data/lib/main.fy +6 -2
  41. data/lib/message_sink.fy +19 -0
  42. data/lib/number.fy +48 -0
  43. data/lib/object.fy +65 -13
  44. data/lib/package.fy +12 -2
  45. data/lib/package/dependency.fy +13 -0
  46. data/lib/package/dependency_installer.fy +27 -0
  47. data/lib/package/installer.fy +4 -10
  48. data/lib/package/uninstaller.fy +1 -3
  49. data/lib/parser/ext/lexer.lex +8 -3
  50. data/lib/parser/ext/parser.y +4 -1
  51. data/lib/parser/methods.fy +7 -3
  52. data/lib/range.fy +1 -1
  53. data/lib/rbx.fy +2 -1
  54. data/lib/rbx/array.fy +28 -12
  55. data/lib/rbx/bignum.fy +1 -1
  56. data/lib/rbx/block.fy +27 -0
  57. data/lib/rbx/console.fy +6 -6
  58. data/lib/rbx/date.fy +6 -1
  59. data/lib/rbx/documentation.fy +8 -3
  60. data/lib/rbx/exception.fy +5 -0
  61. data/lib/rbx/file.fy +40 -7
  62. data/lib/rbx/fixnum.fy +12 -1
  63. data/lib/rbx/method.fy +9 -2
  64. data/lib/rbx/module.fy +24 -0
  65. data/lib/rbx/regexp.fy +8 -0
  66. data/lib/rbx/string.fy +23 -7
  67. data/lib/rbx/tcp_server.fy +4 -2
  68. data/lib/rbx/tcp_socket.fy +14 -0
  69. data/lib/remote_object.fy +59 -0
  70. data/lib/set.fy +15 -4
  71. data/lib/string.fy +38 -5
  72. data/lib/stringio.fy +1 -0
  73. data/lib/symbol.fy +4 -0
  74. data/lib/system.fy +22 -0
  75. data/lib/thread_pool.fy +2 -2
  76. data/lib/tuple.fy +18 -1
  77. data/lib/vars.fy +17 -0
  78. data/lib/version.fy +1 -1
  79. data/ruby_lib/fancy +6 -0
  80. data/tests/array.fy +30 -0
  81. data/tests/block.fy +106 -0
  82. data/tests/class.fy +19 -0
  83. data/tests/enumerable.fy +1 -1
  84. data/tests/enumerator.fy +5 -5
  85. data/tests/file.fy +28 -0
  86. data/tests/fixnum.fy +0 -50
  87. data/tests/future.fy +9 -24
  88. data/tests/hash.fy +35 -0
  89. data/tests/html.fy +33 -0
  90. data/tests/kvo.fy +101 -0
  91. data/tests/number.fy +75 -0
  92. data/tests/object.fy +50 -3
  93. data/tests/string.fy +19 -10
  94. data/tests/symbol.fy +5 -0
  95. data/tests/tuple.fy +7 -0
  96. data/tools/fancy-mode.el +5 -1
  97. metadata +22 -21
  98. data/boot/compiler/parser/ext/fancy_parser.bundle +0 -0
  99. data/boot/rbx-compiler/parser/Makefile +0 -156
  100. data/boot/rbx-compiler/parser/lexer.c +0 -2310
  101. data/boot/rbx-compiler/parser/lexer.h +0 -315
  102. data/boot/rbx-compiler/parser/parser.c +0 -2946
  103. data/boot/rbx-compiler/parser/parser.h +0 -151
  104. data/lib/fiber_pool.fy +0 -78
  105. data/lib/method.fy +0 -6
  106. data/lib/parser/ext/Makefile +0 -156
  107. data/lib/parser/ext/fancy_parser.bundle +0 -0
  108. data/lib/parser/ext/lexer.c +0 -2392
  109. data/lib/parser/ext/lexer.h +0 -315
  110. data/lib/parser/ext/parser.c +0 -3251
  111. data/lib/parser/ext/parser.h +0 -161
@@ -16,28 +16,32 @@ class Fancy AST {
16
16
  @arguments required_args=(@args required_args)
17
17
 
18
18
  if: @partial then: {
19
- first_expr = @body expressions first
19
+ @body = ExpressionList new: @line list: $ @body expressions map: |e| { convert_to_implicit_arg_send: e }
20
+ }
21
+ }
20
22
 
21
- # if first expression is an identifier, use that as a 0-arg
22
- # method name to send to new receiver (use a generated symbol
23
- # name created in lib/parser/methods.fy / Fancy Parser#ast:partial_block:)
24
- # if first expression is a message send where its receiver is
25
- # an identifier, use that as the message name in a send to
26
- # self and use the result as the receiver value for the rest.
27
- new_receiver = Identifier from: (@args args first to_s) line: @line
28
- match first_expr {
29
- case Identifier ->
30
- @body expressions shift()
31
- @body unshift_expression: $ MessageSend new: @line message: first_expr to: (new_receiver) args: (MessageArgs new: @line args: [])
32
- case MessageSend ->
33
- match first_expr receiver {
34
- case Self ->
35
- first_expr receiver: new_receiver
36
- case Identifier ->
37
- first_expr receiver: $ MessageSend new: @line message: (first_expr receiver) to: (new_receiver) args: (MessageArgs new: @line args: [])
38
- }
39
- }
23
+ def convert_to_implicit_arg_send: expr {
24
+ # if expression is an identifier, use that as a 0-arg
25
+ # message name to send to new receiver (use a generated symbol
26
+ # name created in lib/parser/methods.fy / Fancy Parser#ast:partial_block:)
27
+ # if expression is a message send where its receiver is
28
+ # an identifier, use that as the message name in a send to
29
+ # self and use the result as the receiver value for the rest.
30
+ new_receiver = Identifier from: (@args args first to_s) line: @line
31
+ match expr {
32
+ case Identifier ->
33
+ expr = MessageSend new: @line message: expr to: new_receiver args: (MessageArgs new: @line args: [])
34
+ case MessageSend ->
35
+ match expr receiver {
36
+ case Self ->
37
+ expr receiver: new_receiver
38
+ case Identifier ->
39
+ expr receiver: $ MessageSend new: @line message: (expr receiver) to: (new_receiver) args: (MessageArgs new: @line args: [])
40
+ case MessageSend ->
41
+ expr receiver: $ convert_to_implicit_arg_send: $ expr receiver
42
+ }
40
43
  }
44
+ expr
41
45
  }
42
46
 
43
47
  def bytecode: g {
@@ -26,11 +26,22 @@ class Fancy AST {
26
26
  args: args
27
27
  }
28
28
 
29
+ def return_send? {
30
+ match @name {
31
+ case Identifier -> @name string == "return"
32
+ case _ -> false
33
+ }
34
+ }
35
+
29
36
  def bytecode: g {
30
37
  pos(g)
31
38
  if: (@receiver is_a?: Super) then: {
32
39
  SuperSend new: @line message: @name args: @args . bytecode: g
33
40
  } else: {
41
+ if: return_send? then: {
42
+ Return new: @line expr: @receiver . bytecode: g
43
+ return nil
44
+ }
34
45
 
35
46
  # check if we might have a block invocation using block(x,y) syntax.
36
47
  if: ruby_send? then: {
@@ -0,0 +1,60 @@
1
+ class Object {
2
+ def require: require_block ensure: ensure_block body: body_block {
3
+ requirement = Contract Requirement new: require_block
4
+ ensurance = Contract Requirement new: ensure_block
5
+ retval = nil
6
+ requirement if_fullfilled: {
7
+ retval = body_block call
8
+ }
9
+ ensure_block if_fullfilled: {
10
+ retval
11
+ }
12
+ }
13
+
14
+ def require: require_block body: body_block {
15
+ requirement = Contract Requirement new: require_block
16
+ requirement if_fullfilled: {
17
+ body_block call
18
+ }
19
+ }
20
+
21
+ def ensure: ensure_block body: body_block {
22
+ require: ensure_block body: body_block
23
+ }
24
+ }
25
+
26
+ class Contract {
27
+ class RequirementError : RuntimeError
28
+ class Requirement {
29
+ def initialize: @block
30
+ def if_fullfilled: block {
31
+ @block call: [self]
32
+ block call
33
+ }
34
+ def true: expr {
35
+ { RequirementError new: "#{expr} not true" . raise! } unless: expr
36
+ }
37
+ def false: expr {
38
+ { RequirementError new: "#{expr} not false" . raise! } if: expr
39
+ }
40
+ }
41
+ }
42
+
43
+ # # usage:
44
+ # class Fixnum {
45
+ # def / other {
46
+ # require: @{
47
+ # true: $ other is_a?: Fixnum
48
+ # true: $ other > 0
49
+ # # better:
50
+ # other class is: Fixnum
51
+ # other is > 0
52
+ #
53
+ # } body: {
54
+ # "foo" println
55
+ # }
56
+ # }
57
+ # }
58
+
59
+ # f = 10 / 2
60
+ # g = 10 / 0 # requirement error
@@ -0,0 +1,61 @@
1
+ class DynamicSlotObject : BasicObject {
2
+ def initialize {
3
+ @object = Object new
4
+ }
5
+
6
+ def object {
7
+ @object
8
+ }
9
+
10
+ def unknown_message: m with_params: p {
11
+ m to_s split: ":" . each_with_index: |slotname idx| {
12
+ @object set_slot: slotname value: $ p[idx]
13
+ }
14
+ }
15
+ }
16
+
17
+ class DynamicKeyHash : BasicObject {
18
+ def initialize: @deep (false) {
19
+ @hash = <[]>
20
+ }
21
+
22
+ def hash {
23
+ @hash
24
+ }
25
+
26
+ def unknown_message: m with_params: p {
27
+ m to_s split: ":" . each_with_index: |slotname idx| {
28
+ val = p[idx]
29
+ if: @deep then: {
30
+ match val {
31
+ case Block -> val = val to_hash
32
+ }
33
+ }
34
+ @hash[slotname to_sym]: val
35
+ }
36
+ }
37
+ }
38
+
39
+ class DynamicValueArray : BasicObject {
40
+ def initialize {
41
+ @arr = []
42
+ }
43
+
44
+ def array {
45
+ @arr
46
+ }
47
+
48
+ def unknown_message: m with_params: p {
49
+ if: (p size > 0) then: {
50
+ subarr = []
51
+ m to_s split: ":" . each_with_index: |slotname idx| {
52
+ subarr << (slotname to_sym)
53
+ subarr << (p[idx])
54
+ }
55
+ @arr << subarr
56
+ } else: {
57
+ @arr << (m to_s rest to_sym) # skip leading :
58
+ }
59
+ self
60
+ }
61
+ }
@@ -1,533 +1,571 @@
1
- class FancyEnumerable {
2
- """
3
- Mixin-Class with useful methods for collections that implement an @each:@ method.
4
- """
5
-
6
- def includes?: item {
1
+ class Fancy {
2
+ class Enumerable {
7
3
  """
8
- @item Item to check if it's included in @self.
9
- @return @true, if @item in @self, otherwise @false.
10
-
11
- Indicates, if a collection includes a given element.
4
+ Mixin-Class with useful methods for collections that implement an @each:@ method.
12
5
  """
13
6
 
14
- any?: |x| { item == x }
15
- }
7
+ def each_with_index: block {
8
+ """
9
+ @block @Block@ to be called with each element and its index in the @self.
10
+ @return @self
16
11
 
17
- def each: each_block in_between: between_block {
18
- """
19
- Similar to @each:@ but calls an additional @Block@ between
20
- calling the first @Block@ for each element in self.
21
- """
12
+ Iterate over all elements in @self.
13
+ Calls a given @Block@ with each element and its index.
14
+ """
22
15
 
23
- between = { between = between_block }
24
- each: |x| {
25
- between call
26
- each_block call: [x]
16
+ i = 0
17
+ each: |x| {
18
+ block call: [x, i]
19
+ i = i + 1
20
+ }
27
21
  }
28
- }
29
22
 
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.
23
+ def includes?: item {
24
+ """
25
+ @item Item to check if it's included in @self.
26
+ @return @true, if @item in @self, otherwise @false.
34
27
 
35
- Joins a collection with a @String@ between each element, returning a new @String@.
28
+ Indicates, if a collection includes a given element.
29
+ """
36
30
 
37
- \"hello, world\" join: \"-\" # => \"h-e-l-l-o-,- -w-o-r-l-d\"
38
- """
31
+ any?: |x| { item == x }
32
+ }
33
+
34
+ def each: each_block in_between: between_block {
35
+ """
36
+ Similar to @each:@ but calls an additional @Block@ between
37
+ calling the first @Block@ for each element in self.
38
+ """
39
39
 
40
- s = ""
41
- each: |c| {
42
- s << c
43
- } in_between: {
44
- s << str
40
+ between = { between = between_block }
41
+ each: |x| {
42
+ between call
43
+ each_block call: [x]
44
+ }
45
45
  }
46
- s
47
- }
48
46
 
49
- def any?: condition {
50
- """
51
- @condition @Block@ (or @Callable) that is used to check if any element in @self yields true for it.
52
- @return @true, if @condition yields @true for any element, @false otherwise.
47
+ def join: str {
48
+ """
49
+ @str Value (usually a @String@) to be used for the joined @String@.
50
+ @return @String@ containing all elements in @self interspersed with @str.
53
51
 
54
- Indicates, if any element meets the condition.
55
- """
52
+ Joins a collection with a @String@ between each element, returning a new @String@.
53
+
54
+ \"hello, world\" join: \"-\" # => \"h-e-l-l-o-,- -w-o-r-l-d\"
55
+ """
56
56
 
57
- each: |x| {
58
- if: (condition call: [x]) then: {
59
- return true
57
+ s = ""
58
+ each: |c| {
59
+ s << c
60
+ } in_between: {
61
+ s << str
60
62
  }
63
+ s
61
64
  }
62
- false
63
- }
64
65
 
65
- def all?: condition {
66
- """
67
- @block Predicate @Block@ to be called for each element until it returns @false for any one of them.
68
- @return @true if all elements in @self yield @true for @block, @false otherwise.
66
+ def any?: condition {
67
+ """
68
+ @condition @Block@ (or @Callable) that is used to check if any element in @self yields true for it.
69
+ @return @true, if @condition yields @true for any element, @false otherwise.
69
70
 
70
- Takes condition-block and returns @true if all elements meet it.
71
- """
71
+ Indicates, if any element meets the condition.
72
+ """
72
73
 
73
- each: |x| {
74
- unless: (condition call: [x]) do: {
75
- return false
74
+ each: |x| {
75
+ if: (condition call: [x]) then: {
76
+ return true
77
+ }
76
78
  }
79
+ false
77
80
  }
78
- true
79
- }
80
81
 
81
- def find: item {
82
- """
83
- @item Item to be found in @self.
84
- @return The first element that is equal to @item or @nil, if none found.
82
+ def all?: condition {
83
+ """
84
+ @block Predicate @Block@ to be called for each element until it returns @false for any one of them.
85
+ @return @true if all elements in @self yield @true for @block, @false otherwise.
85
86
 
86
- Returns @nil, if @item (or anything that returns @true when comparing to @item) isn't found.
87
- Otherwise returns that element that is equal to @item.
88
- """
87
+ Takes condition-block and returns @true if all elements meet it.
88
+ """
89
89
 
90
- if: (item is_a?: Block) then: {
91
- find_by: item
92
- } else: {
93
90
  each: |x| {
94
- if: (item == x) then: {
95
- return x
91
+ unless: (condition call: [x]) do: {
92
+ return false
96
93
  }
97
94
  }
98
- nil
95
+ true
99
96
  }
100
- }
101
97
 
102
- def find_by: block {
103
- """
104
- Similar to @find:@ but takes a block that is called for each element to find it.
105
- """
98
+ def find: item {
99
+ """
100
+ @item Item to be found in @self.
101
+ @return The first element that is equal to @item or @nil, if none found.
102
+
103
+ Returns @nil, if @item (or anything that returns @true when comparing to @item) isn't found.
104
+ Otherwise returns that element that is equal to @item.
105
+ """
106
106
 
107
- each: |x| {
108
- if: (block call: [x]) then: |item| {
109
- return item
107
+ if: (item is_a?: Block) then: {
108
+ find_by: item
109
+ } else: {
110
+ each: |x| {
111
+ if: (item == x) then: {
112
+ return x
113
+ }
114
+ }
115
+ nil
110
116
  }
111
117
  }
112
- nil
113
- }
114
118
 
115
- def map: block {
116
- """
117
- @block A @Block@ that gets called with each element in @self.
118
- @return An @Array@ containing all values of calling @block with each element in @self.
119
+ def find_by: block {
120
+ """
121
+ Similar to @find:@ but takes a block that is called for each element to find it.
122
+ """
119
123
 
120
- Returns a new @Array@ with the results of calling a given block for every element.
121
- """
124
+ each: |x| {
125
+ if: (block call: [x]) then: {
126
+ return x
127
+ }
128
+ }
129
+ nil
130
+ }
131
+
132
+ def map: block {
133
+ """
134
+ @block A @Block@ that gets called with each element in @self.
135
+ @return An @Array@ containing all values of calling @block with each element in @self.
122
136
 
123
- coll = []
124
- each: |x| {
125
- coll << (block call: [x])
137
+ Returns a new @Array@ with the results of calling a given block for every element.
138
+ """
139
+
140
+ coll = []
141
+ each: |x| {
142
+ coll << (block call: [x])
143
+ }
144
+ coll
126
145
  }
127
- coll
128
- }
129
146
 
130
- def select: condition {
131
- """
132
- @condition A @Block@ that is used as a filter on all elements in @self.
133
- @return An @Array@ containing all elements in @self that yield @true when called with @condition.
147
+ def select: condition {
148
+ """
149
+ @condition A @Block@ that is used as a filter on all elements in @self.
150
+ @return An @Array@ containing all elements in @self that yield @true when called with @condition.
134
151
 
135
- Returns a new @Array@ with all elements that meet the given condition block.
136
- """
152
+ Returns a new @Array@ with all elements that meet the given condition block.
153
+ """
137
154
 
138
- coll = []
139
- each: |x| {
140
- { coll << x } if: $ condition call: [x]
155
+ coll = []
156
+ each: |x| {
157
+ { coll << x } if: $ condition call: [x]
158
+ }
159
+ coll
141
160
  }
142
- coll
143
- }
144
161
 
145
- def reject: condition {
146
- """
147
- Similar to @select:@ but inverse.
148
- Returns a new @Array@ with all elements that don't meet the given condition block.
149
- """
162
+ def reject: condition {
163
+ """
164
+ Similar to @select:@ but inverse.
165
+ Returns a new @Array@ with all elements that don't meet the given condition block.
166
+ """
150
167
 
151
- coll = []
152
- each: |x| {
153
- { coll << x } unless: $ condition call: [x]
168
+ coll = []
169
+ each: |x| {
170
+ { coll << x } unless: $ condition call: [x]
171
+ }
172
+ coll
154
173
  }
155
- coll
156
- }
157
174
 
158
- def take_while: condition {
159
- """
160
- @condition A @Block@ that is used as a condition for filtering.
161
- @return An @Array@ of all elements from the beginning until @condition yields @false.
175
+ def take_while: condition {
176
+ """
177
+ @condition A @Block@ that is used as a condition for filtering.
178
+ @return An @Array@ of all elements from the beginning until @condition yields @false.
162
179
 
163
- Returns a new @Array@ by taking elements from the beginning
164
- as long as they meet the given condition block.
180
+ Returns a new @Array@ by taking elements from the beginning
181
+ as long as they meet the given condition block.
165
182
 
166
- Example:
167
- [1,2,3,4,5] take_while: |x| { x < 4 } # => [1,2,3]
168
- """
183
+ Example:
184
+ [1,2,3,4,5] take_while: |x| { x < 4 } # => [1,2,3]
185
+ """
169
186
 
170
- coll = []
171
- each: |x| {
172
- if: (condition call: [x]) then: {
173
- coll << x
174
- } else: {
175
- return coll
187
+ coll = []
188
+ each: |x| {
189
+ if: (condition call: [x]) then: {
190
+ coll << x
191
+ } else: {
192
+ return coll
193
+ }
176
194
  }
195
+ coll
177
196
  }
178
- coll
179
- }
180
197
 
181
- def drop_while: condition {
182
- """
183
- Similar to @take_while:@ but inverse.
184
- Returns a new @Array@ by skipping elements from the beginning
185
- as long as they meet the given condition block.
198
+ def drop_while: condition {
199
+ """
200
+ Similar to @take_while:@ but inverse.
201
+ Returns a new @Array@ by skipping elements from the beginning
202
+ as long as they meet the given condition block.
186
203
 
187
- Example:
188
- [1,2,3,4,5] drop_while: |x| { x < 4 } # => [4,5]
189
- """
204
+ Example:
205
+ [1,2,3,4,5] drop_while: |x| { x < 4 } # => [4,5]
206
+ """
190
207
 
191
- coll = []
192
- drop = nil
193
- first_check = true
194
- each: |x| {
195
- if: (drop or: first_check) then: {
196
- drop = condition call: [x]
197
- first_check = nil
198
- # check, if we actually have to insert this one:
199
- unless: drop do: {
208
+ coll = []
209
+ drop = nil
210
+ first_check = true
211
+ each: |x| {
212
+ if: (drop or: first_check) then: {
213
+ drop = condition call: [x]
214
+ first_check = nil
215
+ # check, if we actually have to insert this one:
216
+ unless: drop do: {
217
+ coll << x
218
+ }
219
+ } else: {
200
220
  coll << x
201
221
  }
202
- } else: {
203
- coll << x
204
222
  }
223
+ coll
205
224
  }
206
- coll
207
- }
208
225
 
209
- def take: amount {
210
- """
211
- @amount Amount of elements to take from @self.
212
- @return First @amount elements of @self in an @Array@.
226
+ def take: amount {
227
+ """
228
+ @amount Amount of elements to take from @self.
229
+ @return First @amount elements of @self in an @Array@.
213
230
 
214
- Example:
215
- [1,2,3,4] take: 2 # => [1,2]
216
- """
231
+ Example:
232
+ [1,2,3,4] take: 2 # => [1,2]
233
+ """
217
234
 
218
- i = 0
219
- take_while: {
220
- i = i + 1
221
- i <= amount
235
+ i = 0
236
+ take_while: {
237
+ i = i + 1
238
+ i <= amount
239
+ }
222
240
  }
223
- }
224
241
 
225
- def drop: amount {
226
- """
227
- @amount Amount of elements to skip in @self.
228
- @return An @Array@ of all but the first @amount elements in @self.
242
+ def drop: amount {
243
+ """
244
+ @amount Amount of elements to skip in @self.
245
+ @return An @Array@ of all but the first @amount elements in @self.
229
246
 
230
- Example:
231
- [1,2,3,4,5] drop: 2 # => [3,4,5]
232
- """
247
+ Example:
248
+ [1,2,3,4,5] drop: 2 # => [3,4,5]
249
+ """
233
250
 
234
- i = 0
235
- drop_while: {
236
- i = i + 1
237
- i <= amount
251
+ i = 0
252
+ drop_while: {
253
+ i = i + 1
254
+ i <= amount
255
+ }
238
256
  }
239
- }
240
257
 
241
- def reduce: block init_val: init_val {
242
- """
243
- Calculates a value based on a given block to be called on an accumulator
244
- value and an initial value.
258
+ alias_method: 'skip: for: 'drop:
245
259
 
246
- Example:
247
- [1,2,3] reduce: |sum val| { sum + val } init_val: 0 # => 6
248
- """
260
+ def reduce: block init_val: init_val {
261
+ """
262
+ Calculates a value based on a given block to be called on an accumulator
263
+ value and an initial value.
249
264
 
250
- acc = init_val
251
- each: |x| {
252
- acc = (block call: [acc, x])
265
+ Example:
266
+ [1,2,3] reduce: |sum val| { sum + val } init_val: 0 # => 6
267
+ """
268
+
269
+ acc = init_val
270
+ each: |x| {
271
+ acc = (block call: [acc, x])
272
+ }
273
+ acc
253
274
  }
254
- acc
255
- }
256
275
 
257
- def inject: val into: block {
258
- """
259
- Same as reduce:init_val: but taking the initial value as first
260
- and the reducing block as second parameter.
276
+ def inject: val into: block {
277
+ """
278
+ Same as reduce:init_val: but taking the initial value as first
279
+ and the reducing block as second parameter.
261
280
 
262
- Example:
263
- [1,2,3] inject: 0 into: |sum val| { sum + val } # => 6
264
- """
281
+ Example:
282
+ [1,2,3] inject: 0 into: |sum val| { sum + val } # => 6
283
+ """
265
284
 
266
- reduce: block init_val: val
267
- }
285
+ reduce: block init_val: val
286
+ }
268
287
 
269
- def uniq {
270
- """
271
- @return @Array@ of all unique elements in @self.
288
+ def uniq {
289
+ """
290
+ @return @Array@ of all unique elements in @self.
272
291
 
273
- Returns a new Array with all unique values (double entries are skipped).
292
+ Returns a new Array with all unique values (double entries are skipped).
274
293
 
275
- Example:
276
- [1,2,1,2,3] uniq # => [1,2,3]
277
- """
294
+ Example:
295
+ [1,2,1,2,3] uniq # => [1,2,3]
296
+ """
278
297
 
279
- uniq_vals = []
280
- each: |x| {
281
- unless: (uniq_vals includes?: x) do: {
282
- uniq_vals << x
298
+ uniq_vals = []
299
+ each: |x| {
300
+ unless: (uniq_vals includes?: x) do: {
301
+ uniq_vals << x
302
+ }
283
303
  }
304
+ uniq_vals
284
305
  }
285
- uniq_vals
286
- }
287
306
 
288
- def size {
289
- """
290
- @return Amount of elements in @self.
307
+ def size {
308
+ """
309
+ @return Amount of elements in @self.
291
310
 
292
- Returns the size of an Enumerable.
293
- """
311
+ Returns the size of an Enumerable.
312
+ """
294
313
 
295
- i = 0
296
- each: |x| {
297
- i = i + 1
314
+ i = 0
315
+ each: |x| {
316
+ i = i + 1
317
+ }
318
+ i
298
319
  }
299
- i
300
- }
301
320
 
302
- def empty? {
303
- """
304
- @return @true, if size of @self is 0, @false otherwise.
321
+ def empty? {
322
+ """
323
+ @return @true, if size of @self is 0, @false otherwise.
305
324
 
306
- Indicates, if the Enumerable is empty (has no elements).
307
- """
325
+ Indicates, if the Enumerable is empty (has no elements).
326
+ """
308
327
 
309
- size == 0
310
- }
328
+ size == 0
329
+ }
311
330
 
312
- def first {
313
- """
314
- @return First element in @self or @nil, if empty.
315
- """
331
+ def first {
332
+ """
333
+ @return First element in @self or @nil, if empty.
334
+ """
316
335
 
317
- each: |x| {
318
- return x
336
+ each: |x| {
337
+ return x
338
+ }
339
+ nil
319
340
  }
320
- nil
321
- }
322
341
 
323
- def last {
324
- """
325
- @return Last element in @self or @nil, if empty.
342
+ def last {
343
+ """
344
+ @return Last element in @self or @nil, if empty.
326
345
 
327
- Returns the last element in an Enumerable.
328
- """
346
+ Returns the last element in an Enumerable.
347
+ """
329
348
 
330
- item = nil
331
- each: |x| {
332
- item = x
349
+ item = nil
350
+ each: |x| {
351
+ item = x
352
+ }
353
+ item
333
354
  }
334
- item
335
- }
336
355
 
337
- def compact {
338
- """
339
- @return @Array@ with all non-nil elements in @self.
356
+ def compact {
357
+ """
358
+ @return @Array@ with all non-nil elements in @self.
340
359
 
341
- Returns a new @Array@ with all values removed that are @nil ( return @true on @nil? ).
360
+ Returns a new @Array@ with all values removed that are @nil ( return @true on @nil? ).
342
361
 
343
- Example:
344
- [1,2,nil,3,nil] compact # => [1,2,3]
345
- """
362
+ Example:
363
+ [1,2,nil,3,nil] compact # => [1,2,3]
364
+ """
346
365
 
347
- reject: |x| { x nil? }
348
- }
366
+ reject: |x| { x nil? }
367
+ }
349
368
 
350
- def superior_by: comparison_block taking: selection_block ('identity) {
351
- """
352
- @comparison_block @Block@ to be used for comparison.
353
- @selection_block @Block@ to be used for selecting the values to be used for comparison by @comparison_bock.
354
- @return Superior element in @self in terms of @comparison_block.
355
-
356
- Returns the superior element in the @Enumerable that has met
357
- the given comparison block with all other elements,
358
- applied to whatever @selection_block returns for each element.
359
- @selection_block defaults to @identity.
360
-
361
- Examples:
362
- [1,2,5,3,4] superior_by: '> # => 5
363
- [1,2,5,3,4] superior_by: '< # => 1
364
- [[1,2], [2,3,4], [], [1]] superior_by: '> taking: 'size # => [2,3,4]
365
- [[1,2], [2,3,4], [-1]] superior_by: '< taking: 'first # => [-1]
366
- """
369
+ def superior_by: comparison_block taking: selection_block ('identity) {
370
+ """
371
+ @comparison_block @Block@ to be used for comparison.
372
+ @selection_block @Block@ to be used for selecting the values to be used for comparison by @comparison_bock.
373
+ @return Superior element in @self in terms of @comparison_block.
367
374
 
375
+ Returns the superior element in the @Enumerable that has met
376
+ the given comparison block with all other elements,
377
+ applied to whatever @selection_block returns for each element.
378
+ @selection_block defaults to @identity.
368
379
 
369
- pairs = self map: |val| {
370
- (val, selection_block call: [val])
371
- }
380
+ Examples:
381
+ [1,2,5,3,4] superior_by: '> # => 5
382
+ [1,2,5,3,4] superior_by: '< # => 1
383
+ [[1,2], [2,3,4], [], [1]] superior_by: '> taking: 'size # => [2,3,4]
384
+ [[1,2], [2,3,4], [-1]] superior_by: '< taking: 'first # => [-1]
385
+ """
372
386
 
373
- retval = pairs first
374
- pairs each: |p| {
375
- if: (comparison_block call: [p second, retval second]) then: {
376
- retval = p
387
+
388
+ pairs = self map: |val| {
389
+ (val, selection_block call: [val])
377
390
  }
378
- }
379
- retval first
380
- }
381
391
 
382
- def max {
383
- """
384
- @return Maximum value in @self.
392
+ retval = pairs first
393
+ pairs each: |p| {
394
+ if: (comparison_block call: [p second, retval second]) then: {
395
+ retval = p
396
+ }
397
+ }
398
+ retval first
399
+ }
385
400
 
386
- Returns the maximum value in the Enumerable (via the '>' comparison message).
387
- """
401
+ def max {
402
+ """
403
+ @return Maximum value in @self.
388
404
 
389
- superior_by: '>
390
- }
405
+ Returns the maximum value in the Enumerable (via the '>' comparison message).
406
+ """
391
407
 
392
- def min {
393
- """
394
- @return Minimum value in @self.
408
+ superior_by: '>
409
+ }
395
410
 
396
- Returns the minimum value in the Enumerable (via the '<' comparison message).
397
- """
411
+ def min {
412
+ """
413
+ @return Minimum value in @self.
398
414
 
399
- superior_by: '<
400
- }
415
+ Returns the minimum value in the Enumerable (via the '<' comparison message).
416
+ """
401
417
 
402
- def sum {
403
- """
404
- Calculates the sum of all the elements in the @Enumerable
405
- (assuming them to be @Number@s (implementing '+' & '*')).
406
- """
418
+ superior_by: '<
419
+ }
407
420
 
408
- reduce: '+ init_val: 0
409
- }
421
+ def sum {
422
+ """
423
+ Calculates the sum of all the elements in the @Enumerable
424
+ (assuming them to be @Number@s (implementing '+' & '*')).
425
+ """
410
426
 
411
- def product {
412
- """
413
- Calculates the product of all the elements in the @Enumerable
414
- (assuming them to be @Number@s (implementing @+ & @*)).
415
- """
427
+ reduce: '+ init_val: 0
428
+ }
416
429
 
417
- reduce: '* init_val: 1
418
- }
430
+ def product {
431
+ """
432
+ Calculates the product of all the elements in the @Enumerable
433
+ (assuming them to be @Number@s (implementing @+ & @*)).
434
+ """
419
435
 
420
- def average {
421
- """
422
- @return Average value in @self (expecting @Number@s or Objects implementing @+ and @*).
423
- """
436
+ reduce: '* init_val: 1
437
+ }
424
438
 
425
- { return 0 } if: (size == 0)
426
- sum to_f / size
427
- }
439
+ def average {
440
+ """
441
+ @return Average value in @self (expecting @Number@s or Objects implementing @+ and @*).
442
+ """
428
443
 
429
- def partition_by: block {
430
- """
431
- @block @Block@ that gets used to decide when to partition elements in @self.
432
- @return @Array@ of @Array@s, partitioned by equal return values of calling @block with each element
444
+ { return 0 } if: (size == 0)
445
+ sum to_f / size
446
+ }
433
447
 
434
- Example:
435
- 0 upto: 10 . partition_by: |x| { x < 3 } # => [[0, 1, 2], [3, 4, 5, 6, 7, 8, 9, 10]]
436
- """
437
- last = block call: [first]
438
- coll = []
439
- tmp_coll = []
440
- each: |x| {
441
- tmp = block call: [x]
442
- if: (tmp != last) then: {
443
- coll << tmp_coll
444
- tmp_coll = [x]
445
- } else: {
446
- tmp_coll << x
448
+ def partition_by: block {
449
+ """
450
+ @block @Block@ that gets used to decide when to partition elements in @self.
451
+ @return @Array@ of @Array@s, partitioned by equal return values of calling @block with each element
452
+
453
+ Example:
454
+ 0 upto: 10 . partition_by: |x| { x < 3 } # => [[0, 1, 2], [3, 4, 5, 6, 7, 8, 9, 10]]
455
+ """
456
+ last = block call: [first]
457
+ coll = []
458
+ tmp_coll = []
459
+ each: |x| {
460
+ tmp = block call: [x]
461
+ if: (tmp != last) then: {
462
+ coll << tmp_coll
463
+ tmp_coll = [x]
464
+ } else: {
465
+ tmp_coll << x
466
+ }
467
+ last = tmp
447
468
  }
448
- last = tmp
469
+ coll << tmp_coll
470
+ coll
449
471
  }
450
- coll << tmp_coll
451
- coll
452
- }
453
472
 
454
- def random {
455
- """
456
- @return Random element in @self.
457
- """
473
+ def random {
474
+ """
475
+ @return Random element in @self.
476
+ """
458
477
 
459
- at: (rand(size))
460
- }
478
+ at: (rand(size))
479
+ }
461
480
 
462
- def sort_by: block {
463
- """
464
- @block @Block@ taking 2 arguments used to compare elements in a collection.
465
- @return Sorted @Array@ of elements in @self.
481
+ def sort_by: block {
482
+ """
483
+ @block @Block@ taking 2 arguments used to compare elements in a collection.
484
+ @return Sorted @Array@ of elements in @self.
466
485
 
467
- Sorts a collection by a given comparison block.
468
- """
486
+ Sorts a collection by a given comparison block.
487
+ """
469
488
 
470
- if: (block is_a?: Symbol) then: {
471
- sort() |a b| {
472
- a receive_message: block . <=> (b receive_message: block)
489
+ if: (block is_a?: Symbol) then: {
490
+ sort() |a b| {
491
+ a receive_message: block . <=> (b receive_message: block)
492
+ }
493
+ } else: {
494
+ sort(&block)
473
495
  }
474
- } else: {
475
- sort(&block)
476
496
  }
477
- }
478
497
 
479
- def in_groups_of: size {
480
- """
481
- @size Maximum size of each group.
482
- @return @Array@ of @Array@s with a max size of @size (grouped).
498
+ def in_groups_of: size {
499
+ """
500
+ @size Maximum size of each group.
501
+ @return @Array@ of @Array@s with a max size of @size (grouped).
483
502
 
484
- Example usage:
485
- [1,2,3,4,5] in_groups_of: 3 # => [[1,2,3],[4,5]]
486
- """
503
+ Example usage:
504
+ [1,2,3,4,5] in_groups_of: 3 # => [[1,2,3],[4,5]]
505
+ """
487
506
 
488
- groups = []
489
- tmp = []
490
- enum = to_enum
507
+ groups = []
508
+ tmp = []
509
+ enum = to_enum
491
510
 
492
- loop: {
493
- size times: {
494
- tmp << (enum next)
495
- }
511
+ loop: {
512
+ size times: {
513
+ tmp << (enum next)
514
+ }
515
+
516
+ if: (enum ended?) then: {
517
+ { groups << tmp } unless: $ tmp empty?
518
+ break
519
+ }
496
520
 
497
- if: (enum ended?) then: {
498
- { groups << tmp } unless: $ tmp empty?
499
- break
521
+ groups << tmp
522
+ tmp = []
500
523
  }
501
524
 
502
- groups << tmp
503
- tmp = []
525
+ groups
504
526
  }
505
527
 
506
- groups
507
- }
528
+ def reverse {
529
+ """
530
+ @return @self in reverse order.
508
531
 
509
- def reverse {
510
- """
511
- @return @self in reverse order.
532
+ Returns @self in reverse order.
533
+ This only makes sense for collections that have an ordering.
534
+ In either case, it simply converts @self to an @Array@ and returns it in reversed order.
535
+ """
512
536
 
513
- Returns @self in reverse order.
514
- This only makes sense for collections that have an ordering.
515
- In either case, it simply converts @self to an @Array@ and returns it in reversed order.
516
- """
537
+ rev = self to_a
538
+ rev reverse
539
+ }
517
540
 
518
- rev = self to_a
519
- rev reverse
520
- }
541
+ def to_hash: block {
542
+ """
543
+ @block @Block@ to be called to get the key for each element in @self.
544
+ @return @Hash@ of key/value pairs based on values in @self.
521
545
 
522
- def reverse_each: block {
523
- """
524
- @block @Block@ to be called for each element in reverse order.
525
- @return @self
546
+ Example:
547
+ [\"foo\", \”hello\", \"ok\", \"\"] to_hash: @{ size }
548
+ # => <[3 => \"foo\", 5 => \"hello\", 2 => \"ok\", 0 => \"\"]>
549
+ """
526
550
 
527
- Runs @block for each element on reversed version of self.
528
- If @self is not a sorted collection, no guarantees about the reverse order can be given.
529
- """
551
+ h = <[]>
552
+ self each: |val| {
553
+ key = block call: [val]
554
+ h[key]: val
555
+ }
556
+ h
557
+ }
558
+
559
+ def reverse_each: block {
560
+ """
561
+ @block @Block@ to be called for each element in reverse order.
562
+ @return @self
530
563
 
531
- reverse each: block
564
+ Runs @block for each element on reversed version of self.
565
+ If @self is not a sorted collection, no guarantees about the reverse order can be given.
566
+ """
567
+
568
+ reverse each: block
569
+ }
532
570
  }
533
- }
571
+ }