[ruby/strscan] jruby: Check if len++ walked off the end
[ruby.git] / array.rb
blob5f31693cabf2de7b2aac657a0ca9590fb5398178
1 class Array
2   # call-seq:
3   #   shuffle!(random: Random) -> self
4   #
5   # Shuffles all elements in +self+ into a random order,
6   # as selected by the object given by the keyword argument +random+.
7   # Returns +self+:
8   #
9   #   a =             [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
10   #   a.shuffle! # => [5, 3, 8, 7, 6, 1, 9, 4, 2, 0]
11   #   a.shuffle! # => [9, 4, 0, 6, 2, 8, 1, 5, 3, 7]
12   #
13   # Duplicate elements are included:
14   #
15   #   a =             [0, 1, 0, 1, 0, 1, 0, 1, 0, 1]
16   #   a.shuffle! # => [1, 0, 0, 1, 1, 0, 1, 0, 0, 1]
17   #   a.shuffle! # => [0, 1, 0, 1, 1, 0, 1, 0, 1, 0]
18   #
19   # The object given with the keyword argument +random+ is used as the random number generator.
20   #
21   # Related: see {Methods for Assigning}[rdoc-ref:Array@Methods+for+Assigning].
22   def shuffle!(random: Random)
23     Primitive.rb_ary_shuffle_bang(random)
24   end
26   # call-seq:
27   #   shuffle(random: Random) -> new_array
28   #
29   # Returns a new array containing all elements from +self+ in a random order,
30   # as selected by the object given by the keyword argument +random+:
31   #
32   #   a =            [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
33   #   a.shuffle # => [0, 8, 1, 9, 6, 3, 4, 7, 2, 5]
34   #   a.shuffle # => [8, 9, 0, 5, 1, 2, 6, 4, 7, 3]
35   #
36   # Duplicate elements are included:
37   #
38   #   a =            [0, 1, 0, 1, 0, 1, 0, 1, 0, 1]
39   #   a.shuffle # => [1, 0, 1, 1, 0, 0, 1, 0, 0, 1]
40   #   a.shuffle # => [1, 1, 0, 0, 0, 1, 1, 0, 0, 1]
41   #
42   # The object given with the keyword argument +random+ is used as the random number generator.
43   #
44   # Related: see {Methods for Fetching}[rdoc-ref:Array@Methods+for+Fetching].
45   def shuffle(random: Random)
46     Primitive.rb_ary_shuffle(random)
47   end
49   # call-seq:
50   #   sample(random: Random) -> object
51   #   sample(count, random: Random) -> new_ary
52   #
53   # Returns random elements from +self+,
54   # as selected by the object given by the keyword argument +random+.
55   #
56   # With no argument +count+ given, returns one random element from +self+:
57   #
58   #   a = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
59   #   a.sample # => 3
60   #   a.sample # => 8
61   #
62   # Returns +nil+ if +self+ is empty:
63   #
64   #   [].sample # => nil
65   #
66   # With a non-negative numeric argument +count+ given,
67   # returns a new array containing +count+ random elements from +self+:
68   #
69   #   a.sample(3) # => [8, 9, 2]
70   #   a.sample(6) # => [9, 6, 0, 3, 1, 4]
71   #
72   # The order of the result array is unrelated to the order of +self+.
73   #
74   # Returns a new empty array if +self+ is empty:
75   #
76   #   [].sample(4) # => []
77   #
78   # May return duplicates in +self+:
79   #
80   #   a = [1, 1, 1, 2, 2, 3]
81   #   a.sample(a.size) # => [1, 1, 3, 2, 1, 2]
82   #
83   # Returns no more than <tt>a.size</tt> elements
84   # (because no new duplicates are introduced):
85   #
86   #   a.sample(50) # => [6, 4, 1, 8, 5, 9, 0, 2, 3, 7]
87   #
88   # The object given with the keyword argument +random+ is used as the random number generator:
89   #
90   #   a = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
91   #   a.sample(random: Random.new(1))     # => 6
92   #   a.sample(4, random: Random.new(1))  # => [6, 10, 9, 2]
93   #
94   # Related: see {Methods for Fetching}[rdoc-ref:Array@Methods+for+Fetching].
95   def sample(n = (ary = false), random: Random)
96     if Primitive.mandatory_only?
97       # Primitive.cexpr! %{ rb_ary_sample(self, rb_cRandom, Qfalse, Qfalse) }
98       Primitive.ary_sample0
99     else
100       # Primitive.cexpr! %{ rb_ary_sample(self, random, n, ary) }
101       Primitive.ary_sample(random, n, ary)
102     end
103   end
105   # call-seq:
106   #   first -> object or nil
107   #   first(count) -> new_array
108   #
109   # Returns elements from +self+, or +nil+; does not modify +self+.
110   #
111   # With no argument given, returns the first element (if available):
112   #
113   #   a = [:foo, 'bar', 2]
114   #   a.first # => :foo
115   #   a # => [:foo, "bar", 2]
116   #
117   # If +self+ is empty, returns +nil+.
118   #
119   #   [].first # => nil
120   #
121   # With a non-negative integer argument +count+ given,
122   # returns the first +count+ elements (as available) in a new array:
123   #
124   #   a.first(0)  # => []
125   #   a.first(2)  # => [:foo, "bar"]
126   #   a.first(50) # => [:foo, "bar", 2]
127   #
128   # Related: see {Methods for Querying}[rdoc-ref:Array@Methods+for+Querying].
129   def first n = unspecified = true
130     if Primitive.mandatory_only?
131       Primitive.attr! :leaf
132       Primitive.cexpr! %q{ ary_first(self) }
133     else
134       if unspecified
135         Primitive.cexpr! %q{ ary_first(self) }
136       else
137         Primitive.cexpr! %q{  ary_take_first_or_last_n(self, NUM2LONG(n), ARY_TAKE_FIRST) }
138       end
139     end
140   end
142   # call-seq:
143   #  last  -> last_object or nil
144   #  last(count) -> new_array
145   #
146   # Returns elements from +self+, or +nil+; +self+ is not modified.
147   #
148   # With no argument given, returns the last element, or +nil+ if +self+ is empty:
149   #
150   #   a = [:foo, 'bar', 2]
151   #   a.last # => 2
152   #   a # => [:foo, "bar", 2]
153   #   [].last # => nil
154   #
155   #
156   # With non-negative integer argument +count+ given,
157   # returns a new array containing the trailing +count+ elements of +self+, as available:
158   #
159   #   a = [:foo, 'bar', 2]
160   #   a.last(2)  # => ["bar", 2]
161   #   a.last(50) # => [:foo, "bar", 2]
162   #   a.last(0)  # => []
163   #   [].last(3) # => []
164   #
165   # Related: see {Methods for Fetching}[rdoc-ref:Array@Methods+for+Fetching].
166   def last n = unspecified = true
167     if Primitive.mandatory_only?
168       Primitive.attr! :leaf
169       Primitive.cexpr! %q{ ary_last(self) }
170     else
171       if unspecified
172         Primitive.cexpr! %q{ ary_last(self) }
173       else
174         Primitive.cexpr! %q{ ary_take_first_or_last_n(self, NUM2LONG(n), ARY_TAKE_LAST) }
175       end
176     end
177   end
179   # call-seq:
180   #   fetch_values(*indexes) -> new_array
181   #   fetch_values(*indexes) { |index| ... } -> new_array
182   #
183   # With no block given, returns a new array containing the elements of +self+
184   # at the offsets specified by +indexes+. Each of the +indexes+ must be an
185   # {integer-convertible object}[rdoc-ref:implicit_conversion.rdoc@Integer-Convertible+Objects]:
186   #
187   #    a = [:foo, :bar, :baz]
188   #    a.fetch_values(2, 0)   # => [:baz, :foo]
189   #    a.fetch_values(2.1, 0) # => [:baz, :foo]
190   #    a.fetch_values         # => []
191   #
192   # For a negative index, counts backwards from the end of the array:
193   #
194   #    a.fetch_values(-2, -1) # [:bar, :baz]
195   #
196   # When no block is given, raises an exception if any index is out of range.
197   #
198   # With a block given, for each index:
199   #
200   # - If the index is in range, uses an element of +self+ (as above).
201   # - Otherwise, calls the block with the index and uses the block's return value.
202   #
203   # Example:
204   #
205   #   a = [:foo, :bar, :baz]
206   #   a.fetch_values(1, 0, 42, 777) { |index| index.to_s }
207   #   # => [:bar, :foo, "42", "777"]
208   #
209   # Related: see {Methods for Fetching}[rdoc-ref:Array@Methods+for+Fetching].
210   def fetch_values(*indexes, &block)
211     indexes.map! { |i| fetch(i, &block) }
212     indexes
213   end
215   with_yjit do
216     if Primitive.rb_builtin_basic_definition_p(:each)
217       undef :each
219       def each # :nodoc:
220         Primitive.attr! :inline_block, :c_trace
222         unless defined?(yield)
223           return Primitive.cexpr! 'SIZED_ENUMERATOR(self, 0, 0, ary_enum_length)'
224         end
225         _i = 0
226         value = nil
227         while Primitive.cexpr!(%q{ ary_fetch_next(self, LOCAL_PTR(_i), LOCAL_PTR(value)) })
228           yield value
229         end
230         self
231       end
232     end
234     if Primitive.rb_builtin_basic_definition_p(:map)
235       undef :map
237       def map # :nodoc:
238         Primitive.attr! :inline_block, :c_trace
240         unless defined?(yield)
241           return Primitive.cexpr! 'SIZED_ENUMERATOR(self, 0, 0, ary_enum_length)'
242         end
244         _i = 0
245         value = nil
246         result = Primitive.ary_sized_alloc
247         while Primitive.cexpr!(%q{ ary_fetch_next(self, LOCAL_PTR(_i), LOCAL_PTR(value)) })
248           result << yield(value)
249         end
250         result
251       end
253       if Primitive.rb_builtin_basic_definition_p(:collect)
254         undef :collect
255         alias collect map
256       end
257     end
259     if Primitive.rb_builtin_basic_definition_p(:select)
260       undef :select
262       def select # :nodoc:
263         Primitive.attr! :inline_block, :c_trace
265         unless defined?(yield)
266           return Primitive.cexpr! 'SIZED_ENUMERATOR(self, 0, 0, ary_enum_length)'
267         end
269         _i = 0
270         value = nil
271         result = Primitive.ary_sized_alloc
272         while Primitive.cexpr!(%q{ ary_fetch_next(self, LOCAL_PTR(_i), LOCAL_PTR(value)) })
273           result << value if yield value
274         end
275         result
276       end
278       if Primitive.rb_builtin_basic_definition_p(:filter)
279         undef :filter
280         alias filter select
281       end
282     end
283   end