If we have a method on a collection that takes a block with another method executed on each element, we can write it shorter using ampersand. For example: if we have an array of integers and we want to remove the odd numbers we can do this:
[1,2,3,4,5,6,7,8].reject {|x| x.odd?}
Using ampersand, we can write this:
[1,2,3,4,5,6,7,8].reject(&:odd?)
Let's say we have an array of strings, and we want to remove the elements containing 'a'
. We can write the solution like this:
['abc','cba','cbc','cdc','dca','cad','dc','cc].reject {|x| x.include? 'a'}
How do we write this using the ampersand syntax (if it's possible)?
You can't, it is not possible.
&
followed by a symbol is is a shortcut for a method that does not take any arguments.
As you said,
.reject(&:odd?)
Is a shortcut for:
.reject {|x| x.odd?}
Basically, &:SYMBOL
is always a shortcut for passing a block {|x| x.SYMBOL}
The reason this works is because calling the #to_proc method on a symbol returns a lambda expression that's a one-argument lambda, which calls the method with the same name as the symbol on it's argument.
And &
converts from lambda to a block argument -- but beyond that, will call to_proc
on it's operand before converting it to a block argument. So it calls to_proc
on the symbol, and then gets a lambda from the symbol. And then passes this as a block argument to your method.
There's no way to use that shortcut when you need a block whose body goes beyond a one-argument block which just calls the method named after a symbol on it's argument.
Just write it out as you did. Nothing at all wrong with .reject {|x| x.include? 'a'}
, just write that.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With