Array#eachのベンチマーク結果
概要
Array#eachのパフォーマンスが良くなったとのことなので、ベンチマークを取ってみました。
v3.3.5とv3.4.1の比較
prelude: | size = 1_000 arr = Array.new(size) { rand(1..10000) } benchmark: each: | arr.each { |v| v } loop_count: 10000
ips
> bundle exec benchmark-driver benchmark/own/array_each.yml --rbenv '3.3.5; 3.3.5 --yjit; 3.4.1; 3.4.1 --yjit' -v
3.3.5: ruby 3.3.5 (2024-09-03 revision ef084cc8f4) [arm64-darwin23]
3.3.5 --yjit: ruby 3.3.5 (2024-09-03 revision ef084cc8f4) +YJIT [arm64-darwin23]
3.4.1: ruby 3.4.1 (2024-12-25 revision 48d4efcb85) +PRISM [arm64-darwin23]
3.4.1 --yjit: ruby 3.4.1 (2024-12-25 revision 48d4efcb85) +YJIT +PRISM [arm64-darwin23]
Calculating -------------------------------------
3.3.5 3.3.5 --yjit 3.4.1 3.4.1 --yjit
each 51.265k 57.865k 52.145k 58.364k i/s - 10.000k times in 0.195064s 0.172817s 0.191774s 0.171339s
Comparison:
each
3.4.1 --yjit: 58363.8 i/s
3.3.5 --yjit: 57864.7 i/s - 1.01x slower
3.4.1: 52144.7 i/s - 1.12x slower
3.3.5: 51265.2 i/s - 1.14x slower
> bundle exec benchmark-driver benchmark/own/array_each.yml --rbenv '3.3.5; 3.3.5 --yjit; 3.4.1; 3.4.1 --yjit' -v
3.3.5: ruby 3.3.5 (2024-09-03 revision ef084cc8f4) [arm64-darwin23]
3.3.5 --yjit: ruby 3.3.5 (2024-09-03 revision ef084cc8f4) +YJIT [arm64-darwin23]
3.4.1: ruby 3.4.1 (2024-12-25 revision 48d4efcb85) +PRISM [arm64-darwin23]
3.4.1 --yjit: ruby 3.4.1 (2024-12-25 revision 48d4efcb85) +YJIT +PRISM [arm64-darwin23]
Calculating -------------------------------------
3.3.5 3.3.5 --yjit 3.4.1 3.4.1 --yjit
each 51.982k 56.486k 51.148k 58.827k i/s - 10.000k times in 0.192376s 0.177036s 0.195510s 0.169989s
Comparison:
each
3.4.1 --yjit: 58827.3 i/s
3.3.5 --yjit: 56485.7 i/s - 1.04x slower
3.3.5: 51981.5 i/s - 1.13x slower
3.4.1: 51148.3 i/s - 1.15x slower
memory
実行のたびに変わるようです。
> bundle exec benchmark-driver benchmark/own/array_each.yml --rbenv '3.3.5; 3.3.5 --yjit; 3.4.1; 3.4.1 --yjit' -v -r memory
3.3.5: ruby 3.3.5 (2024-09-03 revision ef084cc8f4) [arm64-darwin23]
3.3.5 --yjit: ruby 3.3.5 (2024-09-03 revision ef084cc8f4) +YJIT [arm64-darwin23]
3.4.1: ruby 3.4.1 (2024-12-25 revision 48d4efcb85) +PRISM [arm64-darwin23]
3.4.1 --yjit: ruby 3.4.1 (2024-12-25 revision 48d4efcb85) +YJIT +PRISM [arm64-darwin23]
Calculating -------------------------------------
3.3.5 3.3.5 --yjit 3.4.1 3.4.1 --yjit
each 13.517M 13.828M 13.369M 14.156M bytes - 10.000k times
Comparison:
each
3.4.1: 13369344.0 bytes
3.3.5: 13516800.0 bytes - 1.01x larger
3.3.5 --yjit: 13828096.0 bytes - 1.03x larger
3.4.1 --yjit: 14155776.0 bytes - 1.06x larger
> bundle exec benchmark-driver benchmark/own/array_each.yml --rbenv '3.3.5; 3.3.5 --yjit; 3.4.1; 3.4.1 --yjit' -v -r memory
3.3.5: ruby 3.3.5 (2024-09-03 revision ef084cc8f4) [arm64-darwin23]
3.3.5 --yjit: ruby 3.3.5 (2024-09-03 revision ef084cc8f4) +YJIT [arm64-darwin23]
3.4.1: ruby 3.4.1 (2024-12-25 revision 48d4efcb85) +PRISM [arm64-darwin23]
3.4.1 --yjit: ruby 3.4.1 (2024-12-25 revision 48d4efcb85) +YJIT +PRISM [arm64-darwin23]
Calculating -------------------------------------
3.3.5 3.3.5 --yjit 3.4.1 3.4.1 --yjit
each 13.402M 13.861M 14.352M 14.811M bytes - 10.000k times
Comparison:
each
3.3.5: 13402112.0 bytes
3.3.5 --yjit: 13860864.0 bytes - 1.03x larger
3.4.1: 14352384.0 bytes - 1.07x larger
3.4.1 --yjit: 14811136.0 bytes - 1.11x larger
最近
近況
なんとか。
エンジニアとして興味のあること
CodewarsをRubyで解きながら、自分の解答とベストアンサーをベンチマークで比較することに面白さを感じています。
ChatGPTに解説をしてもらうことでより勉強になります。
課金するか迷っています・・・
ベンチマーク
# Gemfile gem 'benchmark_driver'
# /array_first_take.yml prelude: | size = 1_000_000 arr = Array.new(size) { rand(1..10000) } benchmark: use_first_only: | 100.times { arr.first } use_bracket: | 100.times { arr[0] } use_slice : | 100.times { arr.slice(0) } loop_count: 10000
# 実行
bundle exec benchmark-driver ./array_first_take.yml -v
3.3.5: ruby 3.3.5 (2024-09-03 revision ef084cc8f4) [arm64-darwin23]
Calculating -------------------------------------
use_first 181.419k i/s - 10.000k times in 0.055121s (5.51μs/i)
use_slice 191.732k i/s - 10.000k times in 0.052156s (5.22μs/i)
use_take 194.799k i/s - 10.000k times in 0.051335s (5.13μs/i)
Comparison:
use_take: 194798.9 i/s
use_slice: 191732.5 i/s - 1.02x slower
use_first: 181419.1 i/s - 1.07x slower
面白い・・・
その他興味のあること
2年ほど前にカメラを買いました。
写真を撮りたい、現像ツールも使いこなしたい、そんな最近です。
熱しやすく冷めやすい性格なのが難点のど飴。
なんとか熱があるときに叩き上げたい、そんな来年にしたいです。
Ruby_Array_62
この記事は、以下のドキュメントを改変(自分なりに整理)して利用しています。
class Array (Ruby 3.1 リファレンスマニュアル)
インスタンスメソッド
zip(*lists) -> [ [object] ]
zip(*lists) {|v1, v2, ...| ...} -> nil
- 自身と引数に渡した配列の各要素からなる配列の配列を生成して返す
- ブロック付きで呼び出した場合は、selfと引数に渡した配列の各要素を順番にブロックに渡す
- listsに配列以外のオブジェクトを指定した場合、to_aryメソッドによる暗黙の型変換を試み、それに応答できない場合はeachメソッドんによる暗黙の型変換を試みる。配列以外の(暗黙の型変換が行えない)オブジェクトを指定するとTypeErrorが発生する
irb(main):001:0> [1, 2, 3].zip(['a', 'b', 'c']) => [[1, "a"], [2, "b"], [3, "c"]] irb(main):002:0> [1, 2, 3].zip(['a', 'b', 'c'], [4, 5, 6]) => [[1, "a", 4], [2, "b", 5], [3, "c", 6]] irb(main):003:0> [1, 2, 3, 4, 5].zip(['a', 'b', 'c'], [4, 5, 6]) => [[1, "a", 4], [2, "b", 5], [3, "c", 6], [4, nil, nil], [5, nil, nil]]
irb(main):001:0> arr = [1, 2, 3] => [1, 2, 3] irb(main):002:0> brr = %w[a b c] => ["a", "b", "c"] irb(main):003:0> crr = arr.zip(brr) => [[1, "a"], [2, "b"], [3, "c"]] irb(main):004:0> brr[0].capitalize! => "A" irb(main):005:0> crr => [[1, "A"], [2, "b"], [3, "c"]]
irb(main):001:0> [1, 2, 3].zip => [[1], [2], [3]] irb(main):002:0> [1, 2, 3].zip([]) => [[1, nil], [2, nil], [3, nil]] irb(main):003:0> [].zip([1, 2, 3]) => [] # memo # この挙動は覚えておきたい
irb(main):001:0> [1, 2, 3].zip([4, 5, 6], [7, 8, 9]) { |arr| pp arr } [1, 4, 7] [2, 5, 8] [3, 6, 9] => nil irb(main):002:0> [1, 2, 3].zip([4, 5, 6], [7, 8, 9]) { |v1, v2, v3| pp v2 } 4 5 6 => nil
irb(main):001:0> [1, 2, 3].zip('a') (irb):1:in `zip': wrong argument type String (must respond to :each) (TypeError) from (irb):1:in `<main>' from /Users/mfham/.rbenv/versions/3.1.0/lib/ruby/gems/3.1.0/gems/irb-1.4.1/exe/irb:11:in `<top (required)>' from /Users/mfham/.rbenv/versions/3.1.0/bin/irb:25:in `load' from /Users/mfham/.rbenv/versions/3.1.0/bin/irb:25:in `<main>'
self | other -> Array
- 集合の和演算。両方の配列いずれかに含まれる要素をすべて含む新しい配列を返す
- 重複する要素は取り除かれる
- 重複判定はObject#eql?とObject#hashにより行われる
- 新しい配列における要素の順はselfにおける要素の順と同じ
- otherには配列以外のオブジェクトを指定した場合は to_ary メソッドによる暗黙の型変換を試みる。配列以外の(暗黙の型変換が行えない)オブジェクトを指定した場合TypeErrorが発生する
irb(main):001:0> [1, 2, 3, 1] | [7, 5, 3] => [1, 2, 3, 7, 5] irb(main):002:0> [1, 2, 3, 1, 1.0] | ['1'] => [1, 2, 3, 1.0, "1"] irb(main):003:0> [1, 2, 3] | 'a' (irb):1:in `|': no implicit conversion of String into Array (TypeError) from (irb):1:in `<main>' from /Users/mfham/.rbenv/versions/3.1.0/lib/ruby/gems/3.1.0/gems/irb-1.4.1/exe/irb:11:in `<top (required)>' from /Users/mfham/.rbenv/versions/3.1.0/bin/irb:25:in `load' from /Users/mfham/.rbenv/versions/3.1.0/bin/irb:25:in `<main>'
Ruby_Array_61
この記事は、以下のドキュメントを改変(自分なりに整理)して利用しています。
class Array (Ruby 3.1 リファレンスマニュアル)
インスタンスメソッド
uniq -> Array
uniq! -> self | nil
uniq {|item| ... } -> Array
uniq! {|item| ... } -> self | nil
- uniqは配列から重複した要素を取り除いた新しい配列を返す
- uniq!は削除を破壊的に行い、削除が行われた場合はselfを、そうでなければnilを返す
- この挙動は覚えておきたい
- 要素の重複判定はObject#eql?によって行われる
- ブロックが与えられた場合、ブロックが返した値が重複した要素を取り除いた配列を返す
- 要素を先頭から巡っていき、最初に出現したものが残る
irb(main):001:0> arr = [1, 2, 1] => [1, 2, 1] irb(main):002:0> brr = arr.uniq => [1, 2] irb(main):003:0> arr => [1, 2, 1] irb(main):004:0> brr => [1, 2]
irb(main):001:0> arr = [1, 2, 1] => [1, 2, 1] irb(main):002:0> brr = arr.uniq! => [1, 2] irb(main):003:0> arr => [1, 2] irb(main):004:0> brr => [1, 2]
irb(main):001:0> [1, 2, 3].uniq => [1, 2, 3] irb(main):002:0> [1, 2, 3].uniq! => nil
irb(main):001:0> [1, 1.0, '1'].uniq => [1, 1.0, "1"] irb(main):002:0> [1, 1.0, '1'].uniq { |v| v.to_i } => [1]
irb(main):001:0> v1 = 'e' => "e" irb(main):002:0> v2 = 'e' => "e" irb(main):003:0> arr = [v1, v2] => ["e", "e"] irb(main):004:0> brr = arr.uniq => ["e"] irb(main):005:0> v2.capitalize! => "E" irb(main):006:0> brr => ["e"] irb(main):007:0> v1.capitalize! => "E" irb(main):008:0> brr => ["E"] # memo # 覚えておきたい
values_at(*selectors) -> Array
- 引数で指定されたインデックスに対応する要素を配列で返す
- インデックスに対応する値がなければnilが要素になる
- インデックスは整数もしくは整数のRangeで指定する
irb(main):001:0> arr = %w[a b c d e] => ["a", "b", "c", "d", "e"] irb(main):002:0> arr.values_at(0, 2, 4) => ["a", "c", "e"] irb(main):003:0> arr.values_at(0, 4, 2) => ["a", "e", "c"] irb(main):004:0> arr.values_at(0, 0, 0) => ["a", "a", "a"] irb(main):005:0> arr.values_at(0, 4, 10) => ["a", "e", nil] irb(main):006:0> arr.values_at(-4, -1, -100) => ["b", "e", nil] irb(main):007:0> arr.values_at(0..2) => ["a", "b", "c"] irb(main):008:0> arr.values_at(0..10) => ["a", "b", "c", "d", "e", nil, nil, nil, nil, nil, nil] irb(main):009:0> arr.values_at(5..6) => [nil, nil] irb(main):010:0> arr.values_at(6..7) => [nil, nil] irb(main):011:0> arr.values_at(0, 1..4, 2) => ["a", "b", "c", "d", "e", "c"] # memo # 引数を前から順に処理している感じ
irb(main):001:0> arr = %w[a b c d e] => ["a", "b", "c", "d", "e"] irb(main):002:0> arr.values_at(1.0) => ["b"] irb(main):003:0> arr.values_at(1.8) => ["b"] irb(main):004:0> arr.values_at('1.0') (irb):4:in `values_at': no implicit conversion of String into Integer (TypeError) from (irb):4:in `<main>' from /Users/mfham/.rbenv/versions/3.1.0/lib/ruby/gems/3.1.0/gems/irb-1.4.1/exe/irb:11:in `<top (required)>' from /Users/mfham/.rbenv/versions/3.1.0/bin/irb:25:in `load' from /Users/mfham/.rbenv/versions/3.1.0/bin/irb:25:in `<main>'
Ruby_Array_60
この記事は、以下のドキュメントを改変(自分なりに整理)して利用しています。
class Array (Ruby 3.1 リファレンスマニュアル)
インスタンスメソッド
transpose -> Array
- 自身を行列と見立てて、行列の転置を行い、転置した配列を生成して返す
- 空の配列に対しては空の配列を生成して返す
- 一次元の配列に対してはTypeErrorが、各要素のサイズが不揃いな配列に対してはIndexErrorが発生する
# 1 2 # 3 4 # 5 6 # ↓ # 1 3 5 # 2 4 6 irb(main):001:0> arr = [[1, 2], [3, 4], [5, 6]] => [[1, 2], [3, 4], [5, 6]] irb(main):002:0> arr.transpose => [[1, 3, 5], [2, 4, 6]] irb(main):003:0> arr => [[1, 2], [3, 4], [5, 6]] irb(main):004:0> arr.transpose.transpose => [[1, 2], [3, 4], [5, 6]] irb(main):005:0> [].transpose => []
irb(main):001:0> arr = [['a', 'b'], ['c', 'd']] => [["a", "b"], ["c", "d"]] irb(main):002:0> brr = arr.transpose => [["a", "c"], ["b", "d"]] irb(main):003:0> arr[0][0].capitalize! => "A" irb(main):004:0> arr => [["A", "b"], ["c", "d"]] irb(main):005:0> brr => [["A", "c"], ["b", "d"]]
irb(main):001:0> [1, 2, 3].transpose (irb):1:in `transpose': no implicit conversion of Integer into Array (TypeError) from (irb):1:in `<main>' from /Users/mfham/.rbenv/versions/3.1.0/lib/ruby/gems/3.1.0/gems/irb-1.4.1/exe/irb:11:in `<top (required)>' from /Users/mfham/.rbenv/versions/3.1.0/bin/irb:25:in `load' from /Users/mfham/.rbenv/versions/3.1.0/bin/irb:25:in `<main>' irb(main):002:0> [[1, 2], [3, 4, 5]].transpose (irb):2:in `transpose': element size differs (3 should be 2) (IndexError) from (irb):2:in `<main>' from /Users/mfham/.rbenv/versions/3.1.0/lib/ruby/gems/3.1.0/gems/irb-1.4.1/exe/irb:11:in `<top (required)>' from /Users/mfham/.rbenv/versions/3.1.0/bin/irb:25:in `load' from /Users/mfham/.rbenv/versions/3.1.0/bin/irb:25:in `<main>'
union(*other_arrays) -> Array
- 集合の和演算。重複する要素は取り除かれる
- 重複判定はObject#eql?とObject#hashによって行われる
irb(main):001:0> [1, 'a', 'b'].union([1, 1.0, '1', 'a', 'A']) => [1, "a", "b", 1.0, "1", "A"] irb(main):002:0> [1, 'a', 'b'].union([1, 1.0, '1', 'a', 'A'], ['c']) => [1, "a", "b", 1.0, "1", "A", "c"] irb(main):003:0> [1, 'a', 'b'].union([]) => [1, "a", "b"] irb(main):004:0> [1, 'a', 'b'].union => [1, "a", "b"]
irb(main):001:0> v = 'a' => "a" irb(main):002:0> [v].union([v]) => ["a"] irb(main):003:0> [v].union([v.capitalize!]) => ["A"] irb(main):004:0> ['a'].union(['a'.capitalize!]) => ["a", "A"]
[7] pry(main)> show-source Array#union From: array.c (C Method): Owner: Array Visibility: public Signature: union(*arg1) Number of lines: 29 static VALUE rb_ary_union_multi(int argc, VALUE *argv, VALUE ary) { int i; long sum; VALUE hash, ary_union; sum = RARRAY_LEN(ary); for (i = 0; i < argc; i++) { argv[i] = to_ary(argv[i]); sum += RARRAY_LEN(argv[i]); } if (sum <= SMALL_ARRAY_LEN) { ary_union = rb_ary_new(); rb_ary_union(ary_union, ary); for (i = 0; i < argc; i++) rb_ary_union(ary_union, argv[i]); return ary_union; } hash = ary_make_hash(ary); for (i = 0; i < argc; i++) rb_ary_union_hash(hash, argv[i]); ary_union = rb_hash_values(hash); ary_recycle_hash(hash); return ary_union; } [8] pry(main)> show-source Array#| From: array.c (C Method): Owner: Array Visibility: public Signature: |(arg1) Number of lines: 20 static VALUE rb_ary_or(VALUE ary1, VALUE ary2) { VALUE hash, ary3; ary2 = to_ary(ary2); if (RARRAY_LEN(ary1) + RARRAY_LEN(ary2) <= SMALL_ARRAY_LEN) { ary3 = rb_ary_new(); rb_ary_union(ary3, ary1); rb_ary_union(ary3, ary2); return ary3; } hash = ary_make_hash(ary1); rb_ary_union_hash(hash, ary2); ary3 = rb_hash_values(hash); ary_recycle_hash(hash); return ary3; } # memo # Array#unionとArray#|の内部実装が若干違う # Array#unionは配列を複数受け取るからそこの対応の差なのかな?内部実装はまだ読み解いていない
Ruby_Array_59
この記事は、以下のドキュメントを改変(自分なりに整理)して利用しています。
class Array (Ruby 3.1 リファレンスマニュアル)
インスタンスメソッド
to_a -> Array
- selfを返す
- ただしArray のサブクラスのインスタンスに対して呼ばれたときは自身をArrayに変換したものを返す
irb(main):001:0> arr = [] => [] irb(main):002:0> arr.to_a.class => Array
irb(main):001:0> class Foo < Array irb(main):002:0> end => nil irb(main):003:0> foo = Foo.new => [] irb(main):004:0> foo.to_a.class => Array
to_ary -> self
- selfをそのまま返す
irb(main):001:0> arr = [] => [] irb(main):002:0> arr.to_a.class => Array
irb(main):001:0> class Foo < Array irb(main):002:0> end => nil irb(main):003:0> foo = Foo.new => [] irb(main):004:0> foo.to_ary.class => Foo
to_h -> Hash
to_h { block } -> Hash
- selfを[key, value]のペアの配列として解析し、結果をHashにして返す
- [[k1, v1], [k2, v2], ...]の形式
- ブロックを指定すると、配列の各要素でブロックを呼び出しその結果をペアとして利用する
irb(main):001:0> [['a', 1]].to_h => {"a"=>1} irb(main):002:0> [['a', 1], ['b', 2]].to_h => {"a"=>1, "b"=>2} irb(main):003:0> [['a', 1], ['b', 2], ['c', nil]].to_h => {"a"=>1, "b"=>2, "c"=>nil}
irb(main):002:0> ['a', 1].to_h (irb):2:in `to_h': wrong element type String at 0 (expected array) (TypeError) from (irb):2:in `<main>' from /Users/mfham/.rbenv/versions/3.1.0/lib/ruby/gems/3.1.0/gems/irb-1.4.1/exe/irb:11:in `<top (required)>' from /Users/mfham/.rbenv/versions/3.1.0/bin/irb:25:in `load' from /Users/mfham/.rbenv/versions/3.1.0/bin/irb:25:in `<main>' irb(main):001:0> [['a', 1], ['b']].to_h (irb):1:in `to_h': wrong array length at 1 (expected 2, was 1) (ArgumentError) from (irb):1:in `<main>' from /Users/mfham/.rbenv/versions/3.1.0/lib/ruby/gems/3.1.0/gems/irb-1.4.1/exe/irb:11:in `<top (required)>' from /Users/mfham/.rbenv/versions/3.1.0/bin/irb:25:in `load' from /Users/mfham/.rbenv/versions/3.1.0/bin/irb:25:in `<main>'
irb(main):001:0> [['a', 1], ['b', 2]].to_h { |k, v| [k, v] } => {"a"=>1, "b"=>2} irb(main):002:0> [['a', 1], ['b', 2]].to_h { |k, v| [k.upcase, v + 100] } => {"A"=>101, "B"=>102}
メモ
- to_aryを今知った
Ruby_Array_58
この記事は、以下のドキュメントを改変(自分なりに整理)して利用しています。
class Array (Ruby 3.1 リファレンスマニュアル)
インスタンスメソッド
take(n) -> Array
- 配列の先頭からn要素を配列として返す
- 自身を破壊的には変更しない
irb(main):001:0> arr = %w[a b c d e] => ["a", "b", "c", "d", "e"] irb(main):002:0> arr.take(3) => ["a", "b", "c"] irb(main):003:0> arr => ["a", "b", "c", "d", "e"] irb(main):004:0> arr.take(0) => [] irb(main):005:0> arr.take(10) => ["a", "b", "c", "d", "e"]
irb(main):001:0> arr = %w[a b c d e] => ["a", "b", "c", "d", "e"] irb(main):002:0> arr.take(1.0) => ["a"] irb(main):003:0> arr.take(1.5) => ["a"] irb(main):004:0> arr.take('1') (irb):3:in `take': no implicit conversion of String into Integer (TypeError) from (irb):3:in `<main>' from /Users/mfham/.rbenv/versions/3.1.0/lib/ruby/gems/3.1.0/gems/irb-1.4.1/exe/irb:11:in `<top (required)>' from /Users/mfham/.rbenv/versions/3.1.0/bin/irb:25:in `load' from /Users/mfham/.rbenv/versions/3.1.0/bin/irb:25:in `<main>' irb(main):005:0> arr.take(-1) (irb):4:in `take': attempt to take negative size (ArgumentError) from (irb):4:in `<main>' from /Users/mfham/.rbenv/versions/3.1.0/lib/ruby/gems/3.1.0/gems/irb-1.4.1/exe/irb:11:in `<top (required)>' from /Users/mfham/.rbenv/versions/3.1.0/bin/irb:25:in `load' from /Users/mfham/.rbenv/versions/3.1.0/bin/irb:25:in `<main>'
pry(main)> show-source Array#take From: array.c (C Method): Owner: Array Visibility: public Signature: take(arg1) Number of lines: 9 static VALUE rb_ary_take(VALUE obj, VALUE n) { long len = NUM2LONG(n); if (len < 0) { rb_raise(rb_eArgError, "attempt to take negative size"); } return rb_ary_subseq(obj, 0, len); } pry(main)> show-source Array#slice From: array.c (C Method): Owner: Array Visibility: public Signature: slice(*arg1) Number of lines: 9 VALUE rb_ary_aref(int argc, const VALUE *argv, VALUE ary) { rb_check_arity(argc, 1, 2); if (argc == 2) { return rb_ary_aref2(ary, argv[0], argv[1]); } return rb_ary_aref1(ary, argv[0]); } # memo # 内部ではslice(0, n)と同じことをしていそうだ # https://github.com/ruby/ruby/blob/a51f30c6712798fc07e57f692d0d0e5ccc59acf1/array.c#L1885-L1893
take_while -> Enumerator
take_while {|element| ... } -> Array
- 配列の要素を順に偽になるまでブロックで評価し、最初に偽になった要素の手前の要素までを配列として返す
- 自身を破壊的に変更しない
- ブロックを省略した場合はEnumeratorを返す
irb(main):001:0> arr = [1, 2, 3, 4, 5] => [1, 2, 3, 4, 5] irb(main):002:0> arr.take_while { |v| v < 3 } => [1, 2] irb(main):003:0> arr => [1, 2, 3, 4, 5] irb(main):004:0> arr.take_while { |v| v < 1 } => [] irb(main):005:0> arr.take_while { |v| v < 10 } => [1, 2, 3, 4, 5]
irb(main):001:0> arr = [1, 2, 3, 4, 5] => [1, 2, 3, 4, 5] irb(main):002:0> enum = arr.take_while => #<Enumerator: ...> irb(main):003:0> enum.each { |v| v < 3 } => [1, 2] irb(main):004:0> arr.unshift(0) => [0, 1, 2, 3, 4, 5] irb(main):005:0> enum => #<Enumerator: ...> irb(main):006:0> enum.each { |v| v < 3 } => [0, 1, 2]
メモ
irbの表示が変わっている。要素が少ないときは3.0.0のような表示のほうが個人的にはわかりやすくてよかったかも。
$ ruby -v ruby 3.0.0p0 (2020-12-25 revision 95aff21468) [x86_64-darwin18] $ irb irb(main):001:0> [1, 2, 3].keep_if => #<Enumerator: [1, 2, 3]:keep_if> $ rbenv local 3.1.0 $ ruby -v ruby 3.1.0p0 (2021-12-25 revision fb4df44d16) [x86_64-darwin18] $ irb irb(main):001:0> [1, 2, 3].keep_if => #<Enumerator: ...>