/
enumerable.fnc
204 lines (168 loc) · 4 KB
/
enumerable.fnc
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
def class Enumerable {
"Mixin-Class with useful methods for collections that implement an 'each:' method."
def include?: item {
"Indicates, if a collection includes a given element."
self any?: |x| { item == x }
}
def any?: condition {
"Indicates, if any element meets the condition."
found = nil
self each: |x| {
condition call: [x] . if_true: {
found = true
}
}
found
}
def all?: condition {
"Indicates, if all elements meet the condition."
all = true
self each: |x| {
condition call: [x] . if_false: {
all = nil
}
}
all
}
def find: item {
"Returns nil, if the given object isn't found, or the object, if it is found."
item is_a?: Block . if_true: {
self find_by: item
} else: {
found = nil
self each: |x| {
item == x if_true: {
found = x
}
}
found
}
}
def find_by: block {
"Similar to 'find:' but takes a block that is called for each element to find it."
found = nil
self each: |x| {
block call: [x] . if_do: |item| {
found = item
}
}
found
}
def map: block {
"Returns a new Array with the results of calling a given block for every element"
coll = []
self each: |x| {
coll << (block call: [x])
}
coll
}
def select: condition {
"Returns a new Array with all elements that meet the given condition block."
coll = []
self each: |x| {
{ coll << x } if: $ condition call: [x]
}
coll
}
def reject: condition {
"Returns a new Array with all elements that don't meet the given condition block."
coll = []
self each: |x| {
{ coll << x } unless: $ condition call: [x]
}
coll
}
def take_while: condition {
"Returns a new Array by taking elements from the beginning as long as they meet the given condition block."
coll = []
stop = nil
self each: |x| {
stop if_false: {
condition call: [x] . if_true: {
coll << x
} else: {
stop = true
}
}
}
coll
}
def drop_while: condition {
"Returns a new Array by skipping elements from the beginning as long as they meet the given condition block."
coll = []
drop = nil
first_check = true
self each: |x| {
drop or: first_check . if_true: {
drop = condition call: [x]
first_check = nil
} else: {
coll << x
}
}
coll
}
def reduce: block with: init_val {
"Calculates a value based on a given block to be called on an accumulator value and an initial value."
acc = init_val
self each: |x| {
acc = (block call: [acc, x])
}
acc
}
def uniq {
"Returns a new Array with all unique values (double entries are skipped)."
uniq_vals = []
self each: |x| {
uniq_vals include?: x . if_false: {
uniq_vals << x
}
}
uniq_vals
}
def size {
"Returns the size of an Enumerable."
i = 0
self each: |x| {
i = i + 1
}
i
}
def empty? {
"Indicates, if the Enumerable is empty (has no elements)."
self size == 0
}
def first {
self at: 0
}
def last {
"Returns the last element in an Enumerable."
item = nil
self each: |x| {
item = x
}
item
}
def compact {
"Returns a new Array with all values removed that are nil (return true on nil?)."
self reject: |x| { x nil? }
}
def superior_by: comparison_block {
"Returns the superiour element in the Enumerable that has met the given comparison block with all other elements."
retval = self first
self each: |x| {
comparison_block call: [x, retval] . if_true: {
retval = x
}
}
retval
}
def max {
"Returns the maximum value in the Enumerable (via the '>' comparison message)."
self superior_by: '>
}
def min {
"Returns the minimum value in the Enumerable (via the '<' comparison message)."
self superior_by: '<
}
}