Ruby_Array_57

この記事は、以下のドキュメントを改変(自分なりに整理)して利用しています。

class Array (Ruby 3.1 リファレンスマニュアル)

インスタンスメソッド

sum(init=0) -> object
sum(init=0) {|e| expr } -> object
  • 要素の合計を返す
    • [e1, e2, e3].sumはinit + e1 + e2 + e3を返す
  • ブロックが与えられた場合、加算する前に各要素にブロックが適用される
  • 配列が空の場合、initを返す
  • initを明示的に指定すると数値以外のオブジェクトにも使える
  • "+"メソッドが再定義されている場合、Array#sumは再定義を無視することがある
irb(main):001:0> [1, 2, 3].sum
=> 6

irb(main):002:0> [1, 2, 3].sum(4)
=> 10

irb(main):003:0> [].sum
=> 0

irb(main):004:0> [].sum(10)
=> 10

irb(main):005:0> [1, 2, 3].sum { |v| v * 10 }
=> 60
irb(main):001:0> %w[a b c].sum
(irb):1:in `+': String can't be coerced into Integer (TypeError)
        from (irb):1:in `sum'                                           
        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> %w[a b c].sum('')
=> "abc"

# memo
# initを明示的に指定する必要あり
# %w[a b c].joinのほうが高速
irb(main):001:0> [[1], [2, 3], [4]].sum
(irb):3:in `+': Array can't be coerced into Integer (TypeError)
        from (irb):3:in `sum'                                                           
        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):002:0> [[1], [2, 3], [4]].sum([])
=> [1, 2, 3, 4]

# memo
# initを明示的に指定する必要あり
# [[1], [2, 3], [4]].flattenのほうが高速
$ cat sample1.rb
class Integer
  def +(arg)
    10
  end
end

pp 1 + 2 + 3

pp [1, 2, 3].sum

$ bundle exec ruby sample1.rb
10
6

# "+"を再定義したが、sumで無視されている
# こういう理解で合ってる?
$ cat sample2.rb
class Foo
  def +(arg)
    self
  end
end

foo = Foo.new

pp foo

pp [foo, foo, foo].sum(foo)

$ bundle exec ruby sample2.rb
#<Foo:0x000000010e06c840>
#<Foo:0x000000010e06c840>

メモ

  • sumにinit設定できるのを今知った