Reputation: 368
I know that each_with_object
does not work on immutable objects like integer
.
For example (1..3).each_with_object(0) {|i,sum| sum += i} #=> 0
We can fix this with inject, and the sum will be 6
. Great!
Lets take another example
("a".."c").each_with_object("") {|i,str| str += i} # => ""
This won't work either since when we do str+=i
, we make a new object
Instead we need to do
("a".."c").each_with_object("") {|i,str| str << i} # => "abc"
Why is it that when I do inject
in the following two ways I get weird results
("a".."c").inject("") {|i,str| str += i} # => cba
("a".."c").inject("") {|i,str| str << i} # => ERROR
Why is the first printing abc
in reverse? And why is the second an error?
I know that we should use .each_with_object
for mutable objects, and inject
for immutable (like Integer
), but can I use
.inject
for mutable objects as well just like .each_with_object
? Can anyone explain these results?
Upvotes: 4
Views: 1041
Reputation: 164689
Why is the first printing abc in reverse?
The arguments are backwards. See Enumerable#inject.
Printing i
and str
shows the problem.
$ ruby -e '("a".."c").inject("") {|i,str| puts "i = #{i}"; puts "str = #{str}"; ret = str += i; puts "ret = #{ret}\n\n"; ret }'
i =
str = a
ret = a
i = a
str = b
ret = ba
i = ba
str = c
ret = cba
i
is the accumulated sum returned the last time through the block. str
is the next value. You're adding the previous accumulated value to then end of the next one. You have the arguments backwards. The first one is the sum, the second is the next element.
When that's corrected it works fine.
$ ruby -e 'puts ("a".."c").inject("") {|sum,i| sum += i}'
abc
Furthermore, it's the return value of the block that's used. Altering str
has no effect, it just confuses things further.
$ ruby -e 'puts ("a".."c").inject("") {|sum,i| sum + i}'
abc
And why is the second an error?
It isn't, not in Ruby 2.0.0 nor 2.2.4 anyway. But it has the same problem of backwards args.
$ ruby -e 'puts ("a".."c").inject("") {|i,str| str << i} # => ERROR'
cba
$ ruby -v
ruby 2.2.4p230 (2015-12-16 revision 53155) [x86_64-darwin15]
Upvotes: 3