Skip to content

Instantly share code, notes, and snippets.

Show Gist options
  • Save edmangimelli/0420c02f3c3bae0632a7b91a2d12cf9a to your computer and use it in GitHub Desktop.
Save edmangimelli/0420c02f3c3bae0632a7b91a2d12cf9a to your computer and use it in GitHub Desktop.

When giving a block to a method, I think of it as sending a special proc argument.

You can send regular positional arguments, or kwargs, and you can also send 1 special proc argument.

When you use the literal syntax:

some_method { |x| x.to_s }

it's called a block, though it's really just a special syntax for a proc (special syntax in that it ends up having an elevated status in the method body (see yield)). Now, let's say you wanted to send the same block syntax over and over again:

method_a { |x| x.to_s }
method_b { |x| x.to_s }
method_c { |x| x.to_s }

It kinda stinks to send the literal over and over.

Ruby provides a way to say "use this proc as my block argument" --the ampersand:

to_s_proc = proc { |x| x.to_s }

method_a(&to_s_proc)
method_b(&to_s_proc)
method_c(&to_s_proc)

A shorthand that Ruby provides is supplying a symbol instead of a proc:

method_b(&:to_s)

The symbol is first converted to a proc like so: :to_s.to_proc.

some_symbol.to_proc on a symbol does:

proc { |obj| obj.send :some_symbol }

Note

& is not a general-purpose shorthand for converting a symbol into a proc. It only converts a symbol into a proc in the context of arguments / blocks.

if you do

to_s_proc = &:to_s

you'll get a syntax error, even though this works:

[1,2,3].map(&:to_s)

to make the first example work, you would explicitly call .to_proc:

to_s_proc = :to_s.to_proc
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment