Add 'mrbgems/mruby-pack/' from commit '383a9c79e191d524a9a2b4107cc5043ecbf6190b'
[mruby.git] / mrblib / enum.rb
blob12bd1d37be0133f4d709f33ad61c030dcf4aa6e0
1 ##
2 # Enumerable
4 # The <code>Enumerable</code> mixin provides collection classes with
5 # several traversal and searching methods, and with the ability to
6 # sort. The class must provide a method `each`, which
7 # yields successive members of the collection. If
8 # {Enumerable#max}, {#min}, or
9 # {#sort} is used, the objects in the collection must also
10 # implement a meaningful `<=>` operator, as these methods
11 # rely on an ordering between members of the collection.
13 # @ISO 15.3.2
14 module Enumerable
16   ##
17   # Call the given block for each element
18   # which is yield by +each+. Return false
19   # if one block value is false. Otherwise
20   # return true. If no block is given and
21   # +self+ is false return false.
22   #
23   # ISO 15.3.2.2.1
24   def all?(&block)
25     if block
26       self.each{|*val| return false unless block.call(*val)}
27     else
28       self.each{|*val| return false unless val.__svalue}
29     end
30     true
31   end
33   ##
34   # Call the given block for each element
35   # which is yield by +each+. Return true
36   # if one block value is true. Otherwise
37   # return false. If no block is given and
38   # +self+ is true object return true.
39   #
40   # ISO 15.3.2.2.2
41   def any?(&block)
42     if block
43       self.each{|*val| return true if block.call(*val)}
44     else
45       self.each{|*val| return true if val.__svalue}
46     end
47     false
48   end
50   ##
51   # Call the given block for each element
52   # which is yield by +each+. Append all
53   # values of each block together and
54   # return this value.
55   #
56   # ISO 15.3.2.2.3
57   def collect(&block)
58     return to_enum :collect unless block
60     ary = []
61     self.each{|*val| ary.push(block.call(*val))}
62     ary
63   end
65   ##
66   # Call the given block for each element
67   # which is yield by +each+. Return
68   # +ifnone+ if no block value was true.
69   # Otherwise return the first block value
70   # which had was true.
71   #
72   # ISO 15.3.2.2.4
73   def detect(ifnone=nil, &block)
74     ret = ifnone
75     self.each{|*val|
76       if block.call(*val)
77         ret = val.__svalue
78         break
79       end
80     }
81     ret
82   end
84   ##
85   # Call the given block for each element
86   # which is yield by +each+. Pass an
87   # index to the block which starts at 0
88   # and increase by 1 for each element.
89   #
90   # ISO 15.3.2.2.5
91   def each_with_index(&block)
92     return to_enum :each_with_index unless block
94     i = 0
95     self.each{|*val|
96       block.call(val.__svalue, i)
97       i += 1
98     }
99     self
100   end
102   ##
103   # Return an array of all elements which
104   # are yield by +each+.
105   #
106   # ISO 15.3.2.2.6
107   def entries
108     ary = []
109     self.each{|*val|
110       # __svalue is an internal method
111       ary.push val.__svalue
112     }
113     ary
114   end
116   ##
117   # Alias for find
118   #
119   # ISO 15.3.2.2.7
120   alias find detect
122   ##
123   # Call the given block for each element
124   # which is yield by +each+. Return an array
125   # which contains all elements whose block
126   # value was true.
127   #
128   # ISO 15.3.2.2.8
129   def find_all(&block)
130     return to_enum :find_all unless block
132     ary = []
133     self.each{|*val|
134       ary.push(val.__svalue) if block.call(*val)
135     }
136     ary
137   end
139   ##
140   # Call the given block for each element
141   # which is yield by +each+ and which return
142   # value was true when invoking === with
143   # +pattern+. Return an array with all
144   # elements or the respective block values.
145   #
146   # ISO 15.3.2.2.9
147   def grep(pattern, &block)
148     ary = []
149     self.each{|*val|
150       sv = val.__svalue
151       if pattern === sv
152         ary.push((block)? block.call(*val): sv)
153       end
154     }
155     ary
156   end
158   ##
159   # Return true if at least one element which
160   # is yield by +each+ returns a true value
161   # by invoking == with +obj+. Otherwise return
162   # false.
163   #
164   # ISO 15.3.2.2.10
165   def include?(obj)
166     self.each{|*val|
167       return true if val.__svalue == obj
168     }
169     false
170   end
172   ##
173   # Call the given block for each element
174   # which is yield by +each+. Return value
175   # is the sum of all block values. Pass
176   # to each block the current sum and the
177   # current element.
178   #
179   # ISO 15.3.2.2.11
180   def inject(*args, &block)
181     raise ArgumentError, "too many arguments" if args.size > 2
182     if Symbol === args[-1]
183       sym = args[-1]
184       block = ->(x,y){x.__send__(sym,y)}
185       args.pop
186     end
187     if args.empty?
188       flag = true  # no initial argument
189       result = nil
190     else
191       flag = false
192       result = args[0]
193     end
194     self.each{|*val|
195       val = val.__svalue
196       if flag
197         # push first element as initial
198         flag = false
199         result = val
200       else
201         result = block.call(result, val)
202       end
203     }
204     result
205   end
206   alias reduce inject
208   ##
209   # Alias for collect
210   #
211   # ISO 15.3.2.2.12
212   alias map collect
214   ##
215   # Return the maximum value of all elements
216   # yield by +each+. If no block is given <=>
217   # will be invoked to define this value. If
218   # a block is given it will be used instead.
219   #
220   # ISO 15.3.2.2.13
221   def max(&block)
222     flag = true  # 1st element?
223     result = nil
224     self.each{|*val|
225       val = val.__svalue
226       if flag
227         # 1st element
228         result = val
229         flag = false
230       else
231         if block
232           result = val if block.call(val, result) > 0
233         else
234           result = val if (val <=> result) > 0
235         end
236       end
237     }
238     result
239   end
241   ##
242   # Return the minimum value of all elements
243   # yield by +each+. If no block is given <=>
244   # will be invoked to define this value. If
245   # a block is given it will be used instead.
246   #
247   # ISO 15.3.2.2.14
248   def min(&block)
249     flag = true  # 1st element?
250     result = nil
251     self.each{|*val|
252       val = val.__svalue
253       if flag
254         # 1st element
255         result = val
256         flag = false
257       else
258         if block
259           result = val if block.call(val, result) < 0
260         else
261           result = val if (val <=> result) < 0
262         end
263       end
264     }
265     result
266   end
268   ##
269   # Alias for include?
270   #
271   # ISO 15.3.2.2.15
272   alias member? include?
274   ##
275   # Call the given block for each element
276   # which is yield by +each+. Return an
277   # array which contains two arrays. The
278   # first array contains all elements
279   # whose block value was true. The second
280   # array contains all elements whose
281   # block value was false.
282   #
283   # ISO 15.3.2.2.16
284   def partition(&block)
285     ary_T = []
286     ary_F = []
287     self.each{|*val|
288       if block.call(*val)
289         ary_T.push(val.__svalue)
290       else
291         ary_F.push(val.__svalue)
292       end
293     }
294     [ary_T, ary_F]
295   end
297   ##
298   # Call the given block for each element
299   # which is yield by +each+. Return an
300   # array which contains only the elements
301   # whose block value was false.
302   #
303   # ISO 15.3.2.2.17
304   def reject(&block)
305     ary = []
306     self.each{|*val|
307       ary.push(val.__svalue) unless block.call(*val)
308     }
309     ary
310   end
312   ##
313   # Alias for find_all.
314   #
315   # ISO 15.3.2.2.18
316   alias select find_all
318   ##
319   # Return a sorted array of all elements
320   # which are yield by +each+. If no block
321   # is given <=> will be invoked on each
322   # element to define the order. Otherwise
323   # the given block will be used for
324   # sorting.
325   #
326   # ISO 15.3.2.2.19
327   def sort(&block)
328     self.map{|*val| val.__svalue}.sort
329   end
331   ##
332   # Alias for entries.
333   #
334   # ISO 15.3.2.2.20
335   alias to_a entries
337   # redefine #hash 15.3.1.3.15
338   def hash
339     h = 12347
340     i = 0
341     self.each do |e|
342       n = (e.hash & (0x7fffffff >> (i % 16))) << (i % 16)
343       h ^= n
344       i += 1
345     end
346     h
347   end