Hacker News new | ask | show | jobs
by pmontra 1095 days ago
Or this one?

  3.times.map do
   Thread.new do
     service.call
   end
  end.each(&:join)
I'm not really a fan of those & shortcuts.
1 comments

> I'm not really a fan of those & shortcuts.

One of my favorite parts of ruby!

`collect.each(&:operation)` vs `collection.each { |thing| thing.operation }`

> &:operation

If one is unfamiliar, this syntax will implicitly call `Symbol#to_proc` on `:operation` and pass that as a block to the method (it will work with any object which responds to `#to_proc` and returns an object which responds to `#call`). These lines are all equivalent:

  my_array.map(&:operation)
  my_array.map { |my_element| my_element.operation }
  my_array.map { |my_element| :operation.to_proc.call(my_element) }
Given that, I adore the terseness in the first line, though I can understand a certain annoyance that the shorthand can cause if one doesn't know how this works.
I find it's best to just blindly accept it in Ruby, because you can really go down the rabbit hole otherwise. For example, the first example has even more syntactic fun going on because it looks like `map` accepts an argument but it doesn't:

    irb(main)> [1,2,3].map(1)
    (irb): in `map': wrong number of arguments (given 1, expected 0)
So you get clever and think.. well, it accepts a Proc, clearly, in the shape of &:operation. Let's use a Proc:

    irb(main)> [1,2,3].map(Proc.new { })
    (irb):in `map': wrong number of arguments (given 1, expected 0)
In the context of blocks, & is doing a little more than merely providing a Proc, but it's a handy way to think about it.