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?

Aiden Cullo
  • 312
  • 3
  • 15
Jeff Storey
  • 56,312
  • 72
  • 233
  • 406
  • ruby API docs says `each {|item| block } → ary` so yes `each{block}` method of `Array` class returns `self` – mask8 Jul 22 '12 at 00:48
  • 3
    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. – Casper Jul 22 '12 at 00:50
  • A small point: if no block is present, [1,2,3].each returns [1,2,3].to_enum (at least in Ruby 2.0). – Cary Swoveland Aug 13 '13 at 20:23

4 Answers4

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 }
  • 3
    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 object – Jeff Storey Jul 22 '12 at 00:36
5

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
Markus Andreas
  • 935
  • 1
  • 13
  • 12
  • 6
    OMG `end;nil` IS WHAT I'VE BEEN SEARCHING FOR MY WHOLE LIFE!!! – Andrew Jun 15 '21 at 05:46
  • 1
    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. – Cadoiz Mar 09 '23 at 08:30
  • 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. – Markus Andreas Mar 10 '23 at 20:24
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.

Todd A. Jacobs
  • 81,402
  • 15
  • 141
  • 199
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.

Andrew Grimm
  • 78,473
  • 57
  • 200
  • 338