fancy 0.5.0 → 0.6.0

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