summaryrefslogtreecommitdiff
path: root/array.rb
diff options
context:
space:
mode:
Diffstat (limited to 'array.rb')
-rw-r--r--array.rb210
1 files changed, 118 insertions, 92 deletions
diff --git a/array.rb b/array.rb
index f6c8af8f78..81beff0b1c 100644
--- a/array.rb
+++ b/array.rb
@@ -1,67 +1,22 @@
class Array
# call-seq:
- # each {|element| ... } -> self
- # each -> new_enumerator
- #
- # With a block given, iterates over the elements of +self+,
- # passing each element to the block;
- # returns +self+:
- #
- # a = [:foo, 'bar', 2]
- # a.each {|element| puts "#{element.class} #{element}" }
- #
- # Output:
- #
- # Symbol foo
- # String bar
- # Integer 2
- #
- # Allows the array to be modified during iteration:
- #
- # a = [:foo, 'bar', 2]
- # a.each {|element| puts element; a.clear if element.to_s.start_with?('b') }
- #
- # Output:
- #
- # foo
- # bar
- #
- # With no block given, returns a new Enumerator.
- #
- # Related: see {Methods for Iterating}[rdoc-ref:Array@Methods+for+Iterating].
-
- def each
- Primitive.attr! :inline_block
-
- unless defined?(yield)
- return Primitive.cexpr! 'SIZED_ENUMERATOR(self, 0, 0, ary_enum_length)'
- end
- _i = 0
- value = nil
- while Primitive.cexpr!(%q{ ary_fetch_next(self, LOCAL_PTR(_i), LOCAL_PTR(value)) })
- yield value
- end
- self
- end
-
- # call-seq:
# shuffle!(random: Random) -> self
#
# Shuffles all elements in +self+ into a random order,
- # as selected by the object given by keyword argument +random+;
- # returns +self+:
+ # as selected by the object given by the keyword argument +random+.
+ # Returns +self+:
#
# a = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
# a.shuffle! # => [5, 3, 8, 7, 6, 1, 9, 4, 2, 0]
# a.shuffle! # => [9, 4, 0, 6, 2, 8, 1, 5, 3, 7]
#
- # Duplicate elements are included:
+ # Duplicate elements are included:
#
# a = [0, 1, 0, 1, 0, 1, 0, 1, 0, 1]
# a.shuffle! # => [1, 0, 0, 1, 1, 0, 1, 0, 0, 1]
# a.shuffle! # => [0, 1, 0, 1, 1, 0, 1, 0, 1, 0]
#
- # The object given with keyword argument +random+ is used as the random number generator.
+ # The object given with the keyword argument +random+ is used as the random number generator.
#
# Related: see {Methods for Assigning}[rdoc-ref:Array@Methods+for+Assigning].
def shuffle!(random: Random)
@@ -72,7 +27,7 @@ class Array
# shuffle(random: Random) -> new_array
#
# Returns a new array containing all elements from +self+ in a random order,
- # as selected by the object given by keyword argument +random+:
+ # as selected by the object given by the keyword argument +random+:
#
# a = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
# a.shuffle # => [0, 8, 1, 9, 6, 3, 4, 7, 2, 5]
@@ -84,7 +39,7 @@ class Array
# a.shuffle # => [1, 0, 1, 1, 0, 0, 1, 0, 0, 1]
# a.shuffle # => [1, 1, 0, 0, 0, 1, 1, 0, 0, 1]
#
- # The object given with keyword argument +random+ is used as the random number generator.
+ # The object given with the keyword argument +random+ is used as the random number generator.
#
# Related: see {Methods for Fetching}[rdoc-ref:Array@Methods+for+Fetching].
def shuffle(random: Random)
@@ -96,46 +51,45 @@ class Array
# sample(count, random: Random) -> new_ary
#
# Returns random elements from +self+,
- # as selected by the object given by keyword argument +random+.
+ # as selected by the object given by the keyword argument +random+.
#
# With no argument +count+ given, returns one random element from +self+:
#
- # a = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
- # a.sample # => 3
- # a.sample # => 8
+ # a = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
+ # a.sample # => 3
+ # a.sample # => 8
#
# Returns +nil+ if +self+ is empty:
#
- # [].sample # => nil
- #
+ # [].sample # => nil
#
- # With non-negative numeric argument +count+ given,
+ # With a non-negative numeric argument +count+ given,
# returns a new array containing +count+ random elements from +self+:
#
- # a.sample(3) # => [8, 9, 2]
- # a.sample(6) # => [9, 6, 0, 3, 1, 4]
+ # a.sample(3) # => [8, 9, 2]
+ # a.sample(6) # => [9, 6, 0, 3, 1, 4]
#
# The order of the result array is unrelated to the order of +self+.
#
- # Returns a new empty +Array+ if +self+ is empty:
+ # Returns a new empty array if +self+ is empty:
#
# [].sample(4) # => []
#
# May return duplicates in +self+:
#
- # a = [1, 1, 1, 2, 2, 3]
- # a.sample(a.size) # => [1, 1, 3, 2, 1, 2]
+ # a = [1, 1, 1, 2, 2, 3]
+ # a.sample(a.size) # => [1, 1, 3, 2, 1, 2]
#
# Returns no more than <tt>a.size</tt> elements
# (because no new duplicates are introduced):
#
- # a.sample(50) # => [6, 4, 1, 8, 5, 9, 0, 2, 3, 7]
+ # a.sample(50) # => [6, 4, 1, 8, 5, 9, 0, 2, 3, 7]
#
- # The object given with keyword argument +random+ is used as the random number generator:
+ # The object given with the keyword argument +random+ is used as the random number generator:
#
- # a = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
- # a.sample(random: Random.new(1)) #=> 6
- # a.sample(4, random: Random.new(1)) #=> [6, 10, 9, 2]
+ # a = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
+ # a.sample(random: Random.new(1)) # => 6
+ # a.sample(4, random: Random.new(1)) # => [6, 10, 9, 2]
#
# Related: see {Methods for Fetching}[rdoc-ref:Array@Methods+for+Fetching].
def sample(n = (ary = false), random: Random)
@@ -164,7 +118,7 @@ class Array
#
# [].first # => nil
#
- # With non-negative integer argument +count+ given,
+ # With a non-negative integer argument +count+ given,
# returns the first +count+ elements (as available) in a new array:
#
# a.first(0) # => []
@@ -187,7 +141,7 @@ class Array
# call-seq:
# last -> last_object or nil
- # last(n) -> new_array
+ # last(count) -> new_array
#
# Returns elements from +self+, or +nil+; +self+ is not modified.
#
@@ -199,8 +153,8 @@ class Array
# [].last # => nil
#
#
- # With non-negative integer argument +n+ is given,
- # returns a new array containing the trailing +n+ elements of +self+, as available:
+ # With non-negative integer argument +count+ given,
+ # returns a new array containing the trailing +count+ elements of +self+, as available:
#
# a = [:foo, 'bar', 2]
# a.last(2) # => ["bar", 2]
@@ -222,40 +176,112 @@ class Array
end
end
- # call-seq:
- # fetch_values(*indexes) -> new_array
- # fetch_values(*indexes) {|index| ... } -> new_array
+ # call-seq:
+ # fetch_values(*indexes) -> new_array
+ # fetch_values(*indexes) { |index| ... } -> new_array
#
- # With no block given, returns a new array containing the elements of +self+
- # at the offsets given by +indexes+;
- # each of the +indexes+ must be an
- # {integer-convertible object}[rdoc-ref:implicit_conversion.rdoc@Integer-Convertible+Objects]:
+ # With no block given, returns a new array containing the elements of +self+
+ # at the offsets specified by +indexes+. Each of the +indexes+ must be an
+ # {integer-convertible object}[rdoc-ref:implicit_conversion.rdoc@Integer-Convertible+Objects]:
#
# a = [:foo, :bar, :baz]
- # a.fetch_values(3, 1) # => [:baz, :foo]
- # a.fetch_values(3.1, 1) # => [:baz, :foo]
+ # a.fetch_values(2, 0) # => [:baz, :foo]
+ # a.fetch_values(2.1, 0) # => [:baz, :foo]
# a.fetch_values # => []
#
- # For a negative index, counts backwards from the end of the array:
+ # For a negative index, counts backwards from the end of the array:
#
- # a.fetch_values([-2, -1]) # [:bar, :baz]
+ # a.fetch_values(-2, -1) # [:bar, :baz]
#
- # When no block is given, raises an exception if any index is out of range.
+ # When no block is given, raises an exception if any index is out of range.
#
- # With a block given, for each index:
+ # With a block given, for each index:
#
- # - If the index in in range, uses an element of +self+ (as above).
- # - Otherwise calls, the block with the index, and uses the block's return value.
+ # - If the index is in range, uses an element of +self+ (as above).
+ # - Otherwise, calls the block with the index and uses the block's return value.
#
- # Example:
+ # Example:
#
- # a = [:foo, :bar, :baz]
- # a.fetch_values(1, 0, 42, 777) {|index| index.to_s}
- # # => [:bar, :foo, "42", "777"]
+ # a = [:foo, :bar, :baz]
+ # a.fetch_values(1, 0, 42, 777) { |index| index.to_s }
+ # # => [:bar, :foo, "42", "777"]
#
- # Related: see {Methods for Fetching}[rdoc-ref:Array@Methods+for+Fetching].
+ # Related: see {Methods for Fetching}[rdoc-ref:Array@Methods+for+Fetching].
def fetch_values(*indexes, &block)
indexes.map! { |i| fetch(i, &block) }
indexes
end
+
+ with_jit do
+ if Primitive.rb_builtin_basic_definition_p(:each)
+ undef :each
+
+ def each # :nodoc:
+ Primitive.attr! :inline_block, :c_trace
+
+ unless defined?(yield)
+ return Primitive.cexpr! 'SIZED_ENUMERATOR(self, 0, 0, ary_enum_length)'
+ end
+ _i = 0
+ value = nil
+ while Primitive.cexpr!(%q{ ary_fetch_next(self, LOCAL_PTR(_i), LOCAL_PTR(value)) })
+ yield value
+ end
+ self
+ end
+ end
+
+ if Primitive.rb_builtin_basic_definition_p(:map)
+ undef :map
+
+ def map # :nodoc:
+ Primitive.attr! :inline_block, :c_trace
+
+ unless defined?(yield)
+ return Primitive.cexpr! 'SIZED_ENUMERATOR(self, 0, 0, ary_enum_length)'
+ end
+
+ _i = 0
+ value = nil
+ result = Primitive.ary_sized_alloc
+ while Primitive.cexpr!(%q{ ary_fetch_next(self, LOCAL_PTR(_i), LOCAL_PTR(value)) })
+ value = yield(value)
+ Primitive.cexpr!(%q{ rb_ary_push(result, value) })
+ end
+ result
+ end
+
+ if Primitive.rb_builtin_basic_definition_p(:collect)
+ undef :collect
+ alias collect map
+ end
+ end
+
+ if Primitive.rb_builtin_basic_definition_p(:select)
+ undef :select
+
+ def select # :nodoc:
+ Primitive.attr! :inline_block, :c_trace
+
+ unless defined?(yield)
+ return Primitive.cexpr! 'SIZED_ENUMERATOR(self, 0, 0, ary_enum_length)'
+ end
+
+ _i = 0
+ value = nil
+ result = Primitive.ary_sized_alloc
+ while Primitive.cexpr!(%q{ ary_fetch_next(self, LOCAL_PTR(_i), LOCAL_PTR(value)) })
+ if yield value
+ Primitive.cexpr!(%q{ rb_ary_push(result, value) })
+ end
+ end
+ result
+ end
+
+ if Primitive.rb_builtin_basic_definition_p(:filter)
+ undef :filter
+ alias filter select
+ end
+ end
+ end
end