From: mpapis@... Date: 2014-12-01T19:11:15+00:00 Subject: [ruby-core:66628] [ruby-trunk - misc #10560] confusion between x=x+y, x+=y, x.concat(y) and y.each{|z| x<<z} Issue #10560 has been updated by Michal Papis. Recursive Madman it's what I said in the ticket (but unwinded) Chris Seaton I would assume the `doc` categorization means only the first part was approved to update docs. The rest is optimization and does not have to be part of the specification ... or would it have to be part of specification that cloning object can be dropped if it's not used anywhere else? ---------------------------------------- misc #10560: confusion between x=x+y, x+=y, x.concat(y) and y.each{|z| x<<z} https://bugs.ruby-lang.org/issues/10560#change-50243 * Author: Michal Papis * Status: Assigned * Priority: Normal * Assignee: Zachary Scott * Category: doc * Target version: current: 2.2.0 ---------------------------------------- while discussing a ticket I have noticed that there is no documentation for `+=` I was expecting `+=` to behave as `concat` but instead it behaves as `x=x+y` which for every operation clones the array and updates the variable with new value so it behaves similarly to `x=x.dup.concat(y)` and is slightly faster, but using plane `x.concat(y)` is a lot faster from both `each<<` and `+=` I would either like to get: - updated docs that describe concept of `+=` and show the difference from `concat` - or change `+=` to use `concat` which is faster - and add docs ;) (I would expect `+=` to use `concat` when available) here is a test: require 'benchmark' rep = 10_000 Benchmark.bmbm do |x| { 1..25 => [], "a".."z" => "", }.each do |base, storage| base = base.to_a basej = base class_name = storage.class.to_s x.report(class_name+'#concat') do a = storage.dup basej = base.join if storage == "" rep.times { a.concat(basej) } end x.report(class_name+'#<<') do a = storage.dup basej = base.join if storage == "" rep.times { base.each { |e| a << e } } end x.report(class_name+'#+=') do a = storage.dup basej = base.join if storage == "" rep.times { a += basej } end x.report(class_name+'#dup.concat') do a = storage.dup basej = base.join if storage == "" rep.times { a = a.dup.concat(basej) } end end end and here are results on my machine: user system total real Array#concat 0.000000 0.000000 0.000000 ( 0.001422) Array#<< 0.020000 0.000000 0.020000 ( 0.014356) Array#+= 1.270000 0.230000 1.500000 ( 1.498558) Array#dup.concat 2.720000 0.190000 2.910000 ( 2.915701) String#concat 0.000000 0.000000 0.000000 ( 0.001072) String#<< 0.030000 0.000000 0.030000 ( 0.025828) String#+= 0.130000 0.010000 0.140000 ( 0.135143) String#dup.concat 0.210000 0.020000 0.230000 ( 0.227470) -- https://bugs.ruby-lang.org/