Why does Array#each return an array with the same elements?
Asked Answered
T

4

24

I'm learning the details of how each works in ruby, and I tried out the following line of code:

p [1,2,3,4,5].each { |element| el }

And the result is an array of

[1,2,3,4,5]

Why is the return value of each the same array? Doesn't each just provide a method for iterating? Or is it just common practice for the each method to return the original value?

Turret answered 22/7, 2012 at 0:27 Comment(3)
ruby API docs says each {|item| block } → ary so yes each{block} method of Array class returns selfStenger
The reason is more of a convenience. It's basically a "free" operation for Ruby to return the original array (otherwise it would return nil). As a bonus it allows you to chain methods to further operate on the array if you want.Bouffant
A small point: if no block is present, [1,2,3].each returns [1,2,3].to_enum (at least in Ruby 2.0).Matrix
Q
30

Array#each returns the [array] object it was invoked upon: the result of the block is discarded. Thus if there are no icky side-effects to the original array then nothing will have changed.

Perhaps you mean to use map?

p [1,2,3,4,5].map { |i| i*i }
Quatre answered 22/7, 2012 at 0:35 Comment(1)
I wasn't trying to use map, just wondering why the return value was the same array. But you have confirmed that it just returns the same objectTurret
I
6

If you want, for some reason, to suppress the output (for example debugging in console) here is how you can achive that

  [1,2,3,4,5].each do |nr|
    puts nr.inspect
  end;nil
Invasion answered 21/11, 2018 at 9:8 Comment(3)
OMG end;nil IS WHAT I'VE BEEN SEARCHING FOR MY WHOLE LIFE!!!Greasepaint
Basically end;nil is the same as just a return nil in the next line after end. The return can be omitted, as ruby methods always return the last statement.Triadelphous
Sure, this makes no sense in real code. But a lot of times the return messes up the console. Like in my example where you wan to see the output.Invasion
S
4

Array#each

The block form of Array#each returns the original Array object. You generally use #each when you want to do something with each element of an array inside the block. For example:

[1, 2, 3, 4, 5].each { |element| puts element }

This will print out each element, but returns the original array. You can verify this with:

array = [1, 2, 3, 4, 5]
array.each { |element| element }.object_id === array.object_id
=> true

Array#map

If you want to return a new array, you want to use Array#map or one of its synonyms. The block form of #map returns a different Array object. For example:

array.object_id
=> 25659920
array.map { |element| element }.object_id
=> 20546920
array.map { |element| element }.object_id === array.object_id
=> false

You will generally want to use #map when you want to operate on a modified version of the original array, while leaving the original unchanged.

Sanctitude answered 22/7, 2012 at 0:50 Comment(0)
A
3

All methods return something. Even if it's just a nil object, it returns something.

It may as well return the original object rather than return nil.

Antipasto answered 23/7, 2012 at 23:13 Comment(1)
Right, I was just expecting it to be Nil, though I should have read the docs a little more carefully.Turret

© 2022 - 2024 — McMap. All rights reserved.