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