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.
- data/AUTHORS +2 -0
- data/README.md +6 -1
- data/bin/fancy +6 -0
- data/bin/ifancy +44 -3
- data/boot/fancy_ext/module.rb +4 -0
- data/boot/fancy_ext/object.rb +4 -0
- data/boot/rbx-compiler/compiler/ast/block.rb +29 -1
- data/boot/rbx-compiler/compiler/ast/identifier.rb +6 -0
- data/boot/rbx-compiler/compiler/ast/message_send.rb +1 -0
- data/boot/rbx-compiler/parser/fancy_parser.bundle +0 -0
- data/boot/rbx-compiler/parser/lexer.lex +2 -0
- data/boot/rbx-compiler/parser/parser.rb +6 -0
- data/boot/rbx-compiler/parser/parser.y +14 -1
- data/doc/api/fancy.jsonp +1 -1
- data/doc/features.md +24 -0
- data/examples/99bottles.fy +5 -0
- data/examples/conditions_exceptions.fy +9 -0
- data/examples/conditions_parsing.fy +68 -0
- data/examples/greeter.fy +9 -0
- data/examples/html_generator.fy +59 -29
- data/examples/webserver/webserver.fy +8 -11
- data/lib/argv.fy +6 -0
- data/lib/array.fy +17 -35
- data/lib/block.fy +82 -1
- data/lib/boot.fy +4 -2
- data/lib/compiler.fy +2 -2
- data/lib/compiler/ast/block.fy +24 -20
- data/lib/compiler/ast/message_send.fy +11 -0
- data/lib/contracts.fy +60 -0
- data/lib/dynamic_slot_object.fy +61 -0
- data/lib/enumerable.fy +432 -394
- data/lib/enumerator.fy +152 -150
- data/lib/fdoc.fy +4 -17
- data/lib/fiber.fy +4 -10
- data/lib/file.fy +33 -25
- data/lib/future.fy +59 -5
- data/lib/hash.fy +54 -1
- data/lib/html.fy +107 -0
- data/lib/kvo.fy +173 -0
- data/lib/main.fy +6 -2
- data/lib/message_sink.fy +19 -0
- data/lib/number.fy +48 -0
- data/lib/object.fy +65 -13
- data/lib/package.fy +12 -2
- data/lib/package/dependency.fy +13 -0
- data/lib/package/dependency_installer.fy +27 -0
- data/lib/package/installer.fy +4 -10
- data/lib/package/uninstaller.fy +1 -3
- data/lib/parser/ext/lexer.lex +8 -3
- data/lib/parser/ext/parser.y +4 -1
- data/lib/parser/methods.fy +7 -3
- data/lib/range.fy +1 -1
- data/lib/rbx.fy +2 -1
- data/lib/rbx/array.fy +28 -12
- data/lib/rbx/bignum.fy +1 -1
- data/lib/rbx/block.fy +27 -0
- data/lib/rbx/console.fy +6 -6
- data/lib/rbx/date.fy +6 -1
- data/lib/rbx/documentation.fy +8 -3
- data/lib/rbx/exception.fy +5 -0
- data/lib/rbx/file.fy +40 -7
- data/lib/rbx/fixnum.fy +12 -1
- data/lib/rbx/method.fy +9 -2
- data/lib/rbx/module.fy +24 -0
- data/lib/rbx/regexp.fy +8 -0
- data/lib/rbx/string.fy +23 -7
- data/lib/rbx/tcp_server.fy +4 -2
- data/lib/rbx/tcp_socket.fy +14 -0
- data/lib/remote_object.fy +59 -0
- data/lib/set.fy +15 -4
- data/lib/string.fy +38 -5
- data/lib/stringio.fy +1 -0
- data/lib/symbol.fy +4 -0
- data/lib/system.fy +22 -0
- data/lib/thread_pool.fy +2 -2
- data/lib/tuple.fy +18 -1
- data/lib/vars.fy +17 -0
- data/lib/version.fy +1 -1
- data/ruby_lib/fancy +6 -0
- data/tests/array.fy +30 -0
- data/tests/block.fy +106 -0
- data/tests/class.fy +19 -0
- data/tests/enumerable.fy +1 -1
- data/tests/enumerator.fy +5 -5
- data/tests/file.fy +28 -0
- data/tests/fixnum.fy +0 -50
- data/tests/future.fy +9 -24
- data/tests/hash.fy +35 -0
- data/tests/html.fy +33 -0
- data/tests/kvo.fy +101 -0
- data/tests/number.fy +75 -0
- data/tests/object.fy +50 -3
- data/tests/string.fy +19 -10
- data/tests/symbol.fy +5 -0
- data/tests/tuple.fy +7 -0
- data/tools/fancy-mode.el +5 -1
- metadata +22 -21
- data/boot/compiler/parser/ext/fancy_parser.bundle +0 -0
- data/boot/rbx-compiler/parser/Makefile +0 -156
- data/boot/rbx-compiler/parser/lexer.c +0 -2310
- data/boot/rbx-compiler/parser/lexer.h +0 -315
- data/boot/rbx-compiler/parser/parser.c +0 -2946
- data/boot/rbx-compiler/parser/parser.h +0 -151
- data/lib/fiber_pool.fy +0 -78
- data/lib/method.fy +0 -6
- data/lib/parser/ext/Makefile +0 -156
- data/lib/parser/ext/fancy_parser.bundle +0 -0
- data/lib/parser/ext/lexer.c +0 -2392
- data/lib/parser/ext/lexer.h +0 -315
- data/lib/parser/ext/parser.c +0 -3251
- data/lib/parser/ext/parser.h +0 -161
data/lib/compiler/ast/block.fy
CHANGED
|
@@ -16,28 +16,32 @@ class Fancy AST {
|
|
|
16
16
|
@arguments required_args=(@args required_args)
|
|
17
17
|
|
|
18
18
|
if: @partial then: {
|
|
19
|
-
|
|
19
|
+
@body = ExpressionList new: @line list: $ @body expressions map: |e| { convert_to_implicit_arg_send: e }
|
|
20
|
+
}
|
|
21
|
+
}
|
|
20
22
|
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
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: {
|
data/lib/contracts.fy
ADDED
|
@@ -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
|
+
}
|
data/lib/enumerable.fy
CHANGED
|
@@ -1,533 +1,571 @@
|
|
|
1
|
-
class
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
18
|
-
|
|
19
|
-
|
|
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
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
16
|
+
i = 0
|
|
17
|
+
each: |x| {
|
|
18
|
+
block call: [x, i]
|
|
19
|
+
i = i + 1
|
|
20
|
+
}
|
|
27
21
|
}
|
|
28
|
-
}
|
|
29
22
|
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
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
|
-
|
|
28
|
+
Indicates, if a collection includes a given element.
|
|
29
|
+
"""
|
|
36
30
|
|
|
37
|
-
|
|
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
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
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
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
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
|
-
|
|
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
|
-
|
|
58
|
-
|
|
59
|
-
|
|
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
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
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
|
-
|
|
71
|
-
|
|
71
|
+
Indicates, if any element meets the condition.
|
|
72
|
+
"""
|
|
72
73
|
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
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
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
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
|
-
|
|
87
|
-
|
|
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
|
-
|
|
95
|
-
return
|
|
91
|
+
unless: (condition call: [x]) do: {
|
|
92
|
+
return false
|
|
96
93
|
}
|
|
97
94
|
}
|
|
98
|
-
|
|
95
|
+
true
|
|
99
96
|
}
|
|
100
|
-
}
|
|
101
97
|
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
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
|
-
|
|
108
|
-
|
|
109
|
-
|
|
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
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
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
|
-
|
|
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
|
-
|
|
124
|
-
|
|
125
|
-
|
|
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
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
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
|
-
|
|
136
|
-
|
|
152
|
+
Returns a new @Array@ with all elements that meet the given condition block.
|
|
153
|
+
"""
|
|
137
154
|
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
155
|
+
coll = []
|
|
156
|
+
each: |x| {
|
|
157
|
+
{ coll << x } if: $ condition call: [x]
|
|
158
|
+
}
|
|
159
|
+
coll
|
|
141
160
|
}
|
|
142
|
-
coll
|
|
143
|
-
}
|
|
144
161
|
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
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
|
-
|
|
152
|
-
|
|
153
|
-
|
|
168
|
+
coll = []
|
|
169
|
+
each: |x| {
|
|
170
|
+
{ coll << x } unless: $ condition call: [x]
|
|
171
|
+
}
|
|
172
|
+
coll
|
|
154
173
|
}
|
|
155
|
-
coll
|
|
156
|
-
}
|
|
157
174
|
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
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
|
-
|
|
164
|
-
|
|
180
|
+
Returns a new @Array@ by taking elements from the beginning
|
|
181
|
+
as long as they meet the given condition block.
|
|
165
182
|
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
183
|
+
Example:
|
|
184
|
+
[1,2,3,4,5] take_while: |x| { x < 4 } # => [1,2,3]
|
|
185
|
+
"""
|
|
169
186
|
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
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
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
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
|
-
|
|
188
|
-
|
|
189
|
-
|
|
204
|
+
Example:
|
|
205
|
+
[1,2,3,4,5] drop_while: |x| { x < 4 } # => [4,5]
|
|
206
|
+
"""
|
|
190
207
|
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
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
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
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
|
-
|
|
215
|
-
|
|
216
|
-
|
|
231
|
+
Example:
|
|
232
|
+
[1,2,3,4] take: 2 # => [1,2]
|
|
233
|
+
"""
|
|
217
234
|
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
235
|
+
i = 0
|
|
236
|
+
take_while: {
|
|
237
|
+
i = i + 1
|
|
238
|
+
i <= amount
|
|
239
|
+
}
|
|
222
240
|
}
|
|
223
|
-
}
|
|
224
241
|
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
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
|
-
|
|
231
|
-
|
|
232
|
-
|
|
247
|
+
Example:
|
|
248
|
+
[1,2,3,4,5] drop: 2 # => [3,4,5]
|
|
249
|
+
"""
|
|
233
250
|
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
251
|
+
i = 0
|
|
252
|
+
drop_while: {
|
|
253
|
+
i = i + 1
|
|
254
|
+
i <= amount
|
|
255
|
+
}
|
|
238
256
|
}
|
|
239
|
-
}
|
|
240
257
|
|
|
241
|
-
|
|
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
|
-
|
|
247
|
-
|
|
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
|
-
|
|
251
|
-
|
|
252
|
-
|
|
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
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
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
|
-
|
|
263
|
-
|
|
264
|
-
|
|
281
|
+
Example:
|
|
282
|
+
[1,2,3] inject: 0 into: |sum val| { sum + val } # => 6
|
|
283
|
+
"""
|
|
265
284
|
|
|
266
|
-
|
|
267
|
-
|
|
285
|
+
reduce: block init_val: val
|
|
286
|
+
}
|
|
268
287
|
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
288
|
+
def uniq {
|
|
289
|
+
"""
|
|
290
|
+
@return @Array@ of all unique elements in @self.
|
|
272
291
|
|
|
273
|
-
|
|
292
|
+
Returns a new Array with all unique values (double entries are skipped).
|
|
274
293
|
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
294
|
+
Example:
|
|
295
|
+
[1,2,1,2,3] uniq # => [1,2,3]
|
|
296
|
+
"""
|
|
278
297
|
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
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
|
-
|
|
289
|
-
|
|
290
|
-
|
|
307
|
+
def size {
|
|
308
|
+
"""
|
|
309
|
+
@return Amount of elements in @self.
|
|
291
310
|
|
|
292
|
-
|
|
293
|
-
|
|
311
|
+
Returns the size of an Enumerable.
|
|
312
|
+
"""
|
|
294
313
|
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
314
|
+
i = 0
|
|
315
|
+
each: |x| {
|
|
316
|
+
i = i + 1
|
|
317
|
+
}
|
|
318
|
+
i
|
|
298
319
|
}
|
|
299
|
-
i
|
|
300
|
-
}
|
|
301
320
|
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
321
|
+
def empty? {
|
|
322
|
+
"""
|
|
323
|
+
@return @true, if size of @self is 0, @false otherwise.
|
|
305
324
|
|
|
306
|
-
|
|
307
|
-
|
|
325
|
+
Indicates, if the Enumerable is empty (has no elements).
|
|
326
|
+
"""
|
|
308
327
|
|
|
309
|
-
|
|
310
|
-
|
|
328
|
+
size == 0
|
|
329
|
+
}
|
|
311
330
|
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
331
|
+
def first {
|
|
332
|
+
"""
|
|
333
|
+
@return First element in @self or @nil, if empty.
|
|
334
|
+
"""
|
|
316
335
|
|
|
317
|
-
|
|
318
|
-
|
|
336
|
+
each: |x| {
|
|
337
|
+
return x
|
|
338
|
+
}
|
|
339
|
+
nil
|
|
319
340
|
}
|
|
320
|
-
nil
|
|
321
|
-
}
|
|
322
341
|
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
342
|
+
def last {
|
|
343
|
+
"""
|
|
344
|
+
@return Last element in @self or @nil, if empty.
|
|
326
345
|
|
|
327
|
-
|
|
328
|
-
|
|
346
|
+
Returns the last element in an Enumerable.
|
|
347
|
+
"""
|
|
329
348
|
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
349
|
+
item = nil
|
|
350
|
+
each: |x| {
|
|
351
|
+
item = x
|
|
352
|
+
}
|
|
353
|
+
item
|
|
333
354
|
}
|
|
334
|
-
item
|
|
335
|
-
}
|
|
336
355
|
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
356
|
+
def compact {
|
|
357
|
+
"""
|
|
358
|
+
@return @Array@ with all non-nil elements in @self.
|
|
340
359
|
|
|
341
|
-
|
|
360
|
+
Returns a new @Array@ with all values removed that are @nil ( return @true on @nil? ).
|
|
342
361
|
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
362
|
+
Example:
|
|
363
|
+
[1,2,nil,3,nil] compact # => [1,2,3]
|
|
364
|
+
"""
|
|
346
365
|
|
|
347
|
-
|
|
348
|
-
|
|
366
|
+
reject: |x| { x nil? }
|
|
367
|
+
}
|
|
349
368
|
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
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
|
-
|
|
370
|
-
|
|
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
|
-
|
|
374
|
-
|
|
375
|
-
|
|
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
|
-
|
|
383
|
-
|
|
384
|
-
|
|
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
|
-
|
|
387
|
-
|
|
401
|
+
def max {
|
|
402
|
+
"""
|
|
403
|
+
@return Maximum value in @self.
|
|
388
404
|
|
|
389
|
-
|
|
390
|
-
|
|
405
|
+
Returns the maximum value in the Enumerable (via the '>' comparison message).
|
|
406
|
+
"""
|
|
391
407
|
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
@return Minimum value in @self.
|
|
408
|
+
superior_by: '>
|
|
409
|
+
}
|
|
395
410
|
|
|
396
|
-
|
|
397
|
-
|
|
411
|
+
def min {
|
|
412
|
+
"""
|
|
413
|
+
@return Minimum value in @self.
|
|
398
414
|
|
|
399
|
-
|
|
400
|
-
|
|
415
|
+
Returns the minimum value in the Enumerable (via the '<' comparison message).
|
|
416
|
+
"""
|
|
401
417
|
|
|
402
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
421
|
-
|
|
422
|
-
@return Average value in @self (expecting @Number@s or Objects implementing @+ and @*).
|
|
423
|
-
"""
|
|
436
|
+
reduce: '* init_val: 1
|
|
437
|
+
}
|
|
424
438
|
|
|
425
|
-
|
|
426
|
-
|
|
427
|
-
|
|
439
|
+
def average {
|
|
440
|
+
"""
|
|
441
|
+
@return Average value in @self (expecting @Number@s or Objects implementing @+ and @*).
|
|
442
|
+
"""
|
|
428
443
|
|
|
429
|
-
|
|
430
|
-
|
|
431
|
-
|
|
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
|
-
|
|
435
|
-
|
|
436
|
-
|
|
437
|
-
|
|
438
|
-
|
|
439
|
-
|
|
440
|
-
|
|
441
|
-
|
|
442
|
-
|
|
443
|
-
|
|
444
|
-
|
|
445
|
-
|
|
446
|
-
|
|
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
|
-
|
|
469
|
+
coll << tmp_coll
|
|
470
|
+
coll
|
|
449
471
|
}
|
|
450
|
-
coll << tmp_coll
|
|
451
|
-
coll
|
|
452
|
-
}
|
|
453
472
|
|
|
454
|
-
|
|
455
|
-
|
|
456
|
-
|
|
457
|
-
|
|
473
|
+
def random {
|
|
474
|
+
"""
|
|
475
|
+
@return Random element in @self.
|
|
476
|
+
"""
|
|
458
477
|
|
|
459
|
-
|
|
460
|
-
|
|
478
|
+
at: (rand(size))
|
|
479
|
+
}
|
|
461
480
|
|
|
462
|
-
|
|
463
|
-
|
|
464
|
-
|
|
465
|
-
|
|
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
|
-
|
|
468
|
-
|
|
486
|
+
Sorts a collection by a given comparison block.
|
|
487
|
+
"""
|
|
469
488
|
|
|
470
|
-
|
|
471
|
-
|
|
472
|
-
|
|
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
|
-
|
|
480
|
-
|
|
481
|
-
|
|
482
|
-
|
|
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
|
-
|
|
485
|
-
|
|
486
|
-
|
|
503
|
+
Example usage:
|
|
504
|
+
[1,2,3,4,5] in_groups_of: 3 # => [[1,2,3],[4,5]]
|
|
505
|
+
"""
|
|
487
506
|
|
|
488
|
-
|
|
489
|
-
|
|
490
|
-
|
|
507
|
+
groups = []
|
|
508
|
+
tmp = []
|
|
509
|
+
enum = to_enum
|
|
491
510
|
|
|
492
|
-
|
|
493
|
-
|
|
494
|
-
|
|
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
|
-
|
|
498
|
-
|
|
499
|
-
break
|
|
521
|
+
groups << tmp
|
|
522
|
+
tmp = []
|
|
500
523
|
}
|
|
501
524
|
|
|
502
|
-
groups
|
|
503
|
-
tmp = []
|
|
525
|
+
groups
|
|
504
526
|
}
|
|
505
527
|
|
|
506
|
-
|
|
507
|
-
|
|
528
|
+
def reverse {
|
|
529
|
+
"""
|
|
530
|
+
@return @self in reverse order.
|
|
508
531
|
|
|
509
|
-
|
|
510
|
-
|
|
511
|
-
|
|
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
|
-
|
|
514
|
-
|
|
515
|
-
|
|
516
|
-
"""
|
|
537
|
+
rev = self to_a
|
|
538
|
+
rev reverse
|
|
539
|
+
}
|
|
517
540
|
|
|
518
|
-
|
|
519
|
-
|
|
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
|
-
|
|
523
|
-
|
|
524
|
-
|
|
525
|
-
|
|
546
|
+
Example:
|
|
547
|
+
[\"foo\", \”hello\", \"ok\", \"\"] to_hash: @{ size }
|
|
548
|
+
# => <[3 => \"foo\", 5 => \"hello\", 2 => \"ok\", 0 => \"\"]>
|
|
549
|
+
"""
|
|
526
550
|
|
|
527
|
-
|
|
528
|
-
|
|
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
|
-
|
|
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
|
+
}
|