All original content is created in Ukrainian. Not all content has been translated yet. Some posts may only be available in Ukrainian.Learn more

What happens if you call [1, 2, 3].map(&Person)

Post cover: What happens if you call [1, 2, 3].map(&Person)
Table of contentsClick link to navigate to the desired location
This content has been automatically translated from Ukrainian.
At first glance, such code seems strange - we usually write map(&:to_s) or map { |x| ... }. But Ruby allows you to pass not only characters, but any objects after &if they can turn into Proc through the to_proc method.
When Ruby sees &Person, it calls: Person.to_proc
That is, trying to turn Person into a Proc object.
The resulting Proc object is used as block for the map method.
Next, Ruby calls this Proc - for each element of the array proc.call(element)
Example
class Person
  def initialize(name)
    @name = name
  end

  def self.to_proc
    ->(name) { new(name) }
  end
end

people = ["Bant", "Yuki", "Beanie"].map(&Person)
p people
Result:
[#<Person:0x0000000103f2b3a8 @name="Bant">,
 #<Person:0x0000000103f2b0b0 @name="Yuki">,
 #<Person:0x0000000103f2adb8 @name="Beanie">]
What really happens under the hood?
Ruby calls yours Person.to_proc, which returns lambda:
->(name) { Person.new(name) } # note that we missed Person in the method (optional to specify))
And then actually does the same thing as:
["Oleh", "Ira", "Marta"].map { |name| Person.new(name) }

How does .call work?

Each Proc or lambda has a.call method that runs stored code inside. That is, when Ruby makes a proc.call(element), it actually executes your block:
my_proc = ->(x) { puts "Hello, #{x}" }
my_proc.call("Ruby") # => "Hello, Ruby"
In short:
  • &obj in Ruby → calls obj.to_proc.
  • The result must be Proc or lambda.
  • Ruby then calls proc.call(x) for each element.
  • Therefore map(&Person) works if the class has the self.to_proc method.
We will consider the last point in a little more detail. If the class does not have a .to_proc method - wait for an error. Why?
[1, 2, 3].map(&123)
What Ruby does:
  1. sees &123
  2. thinks: “yes, you need to call 123.to_proc”
  3. but in numbers (Integer) there is no method to_proc
  4. so - an error
irb(main):001> 123.to_proc
(irb):1:in `<main>’: undefined method osulto_proc' for 123:Integer (NoMethodError)

123.to_proc
   ^^^^^^^^
Did you mean?  to_r
from /Users/mykyta/.rbenv/versions/3.2.1/lib/ruby/gems/3.2.0/gems/irb-1.15.2/exe/irb:9:in `<top (required)>'
from/Users/mykyta/.rbenv/versions/3.2.1/bin/irb:25:in lessload'
from /Users/mykyta/.rbenv/versions/3.2.1/bin/irb:25:in `<main>’
irb(main):002> 

This post doesn't have any additions from the author yet.

How arrays work in Ruby: practical examples each, map, select, inject, reduce, filter_map
28 Oct 10:38

How arrays work in Ruby: practical examples each, map, select, inject, reduce, filter_map

Нотатки про Ruby та RoR
Нотатки про Ruby та RoR@kovbaska
How self, protected and private (Ruby) works
28 Oct 13:52

How self, protected and private (Ruby) works

Нотатки про Ruby та RoR
Нотатки про Ruby та RoR@kovbaska
Integer division in Ruby: why 6/4 is 1
28 Oct 14:10

Integer division in Ruby: why 6/4 is 1

Нотатки про Ruby та RoR
Нотатки про Ruby та RoR@kovbaska
28 Oct 14:42

How &:to_s works in Ruby and what Symbol#to_proc is

Нотатки про Ruby та RoR
Нотатки про Ruby та RoR@kovbaska
What are Proc and Lambda in Ruby?
28 Oct 15:57

What are Proc and Lambda in Ruby?

Нотатки про Ruby та RoR
Нотатки про Ruby та RoR@kovbaska
Singleton class (eigenclass) in Ruby: what it is and why it is needed
29 Oct 18:29

Singleton class (eigenclass) in Ruby: what it is and why it is needed

Нотатки про Ruby та RoR
Нотатки про Ruby та RoR@kovbaska
==, equal?, eql?, === in Ruby: what is checked and when to use
29 Oct 20:47

==, equal?, eql?, === in Ruby: what is checked and when to use

Нотатки про Ruby та RoR
Нотатки про Ruby та RoR@kovbaska
Include, Extend, Prepend in Ruby: how they work and what's the difference
29 Oct 21:20

Include, Extend, Prepend in Ruby: how they work and what's the difference

Нотатки про Ruby та RoR
Нотатки про Ruby та RoR@kovbaska
module_function in Ruby: When module methods are available as modular and as functions
29 Oct 21:53

module_function in Ruby: When module methods are available as modular and as functions

Нотатки про Ruby та RoR
Нотатки про Ruby та RoR@kovbaska
What is memoization in Ruby?
30 Oct 10:17

What is memoization in Ruby?

Нотатки про Ruby та RoR
Нотатки про Ruby та RoR@kovbaska
is_a?, kind_of?, instance_of? — how does Ruby check object type?
30 Oct 19:55

is_a?, kind_of?, instance_of? — how does Ruby check object type?

Нотатки про Ruby та RoR
Нотатки про Ruby та RoR@kovbaska