Reputation: 25
I've been trying to collect arrays with digits into one array. If I try to use + it returns emty array as output. Using concat returns expected array of digits. How does it work and what the main difference between these Ruby methods?
0.step.with_object([]) do |index, output|
output + [index]
break output if index == 100
do # returns empty array
0.step.with_object([]) do |index, output|
output.concat [index]
break output if index == 100
end # returns an array contains digits from 0 to 100
Upvotes: 2
Views: 231
Reputation: 110675
Let's create two arrays:
a = [1, 2]
b = [3, 4]
Like all objects, these arrays have unique object ids:
a.object_id #=> 48242540181360
b.object_id #=> 48242540299680
Now let's add them together:
c = a + b #=> [1, 2, 3, 4]
This creates a new object (held by the variable c
):
c.object_id #=> 48242540315060
and leaves (the objects held by) a
and b
(and their object ids) unchanged:
a #=> [1, 2]
b #=> [3, 4]
Now, let's write:
a += b #=> [1, 2, 3, 4]
which Ruby changes to:
a = a + b
when it compiles the code. We obtain:
a #=> [1, 2, 3, 4]
a.object_id #=> 48242541482040
The variable a
now holds a new object that equals the previous value of a
plus b
.
Now let's concatenate b
with (the new value of) a
:
a.concat(b) #=> [1, 2, 3, 4, 3, 4]
This changes (mutates) a
, but of course does not change a
's object id:
a #=> [1, 2, 3, 4, 3, 4]
a.object_id #=> 48242541482040
Lastly, we could replace a
's value with c
, without affecting a
's object id:
a.replace(c) #=> [1, 2, 3, 4]
a #=> [1, 2, 3, 4]
a.object_id #=> 48242541482040
See Array#+, Array#concat and Array#replace.
Upvotes: 1
Reputation: 121000
Unlike Enumerable#reduce
, Enumerable#each_with_object
passes the same object through reducing process.
Array#+
creates a new instance, leaving the original object unrouched.
Array#concat
mutates the original object.
With reduce
the result will be the same:
0.step.reduce([]) do |acc, index|
break acc if index > 100
acc + [index]
end
Upvotes: 5