You\'re probably familiar with the following Ruby shorthand (a
is an array):
a.map(&:method)
For example, try the followin
Short answer: No.
Following @rkon's answer, you could also do this:
a = [1,3,5,7,9]
a.map &->(_) { _ + 2 } # => [3, 5, 7, 9, 11]
I'm not sure about the Symbol#with
already posted, I simplified it quite a bit and it works well:
class Symbol
def with(*args, &block)
lambda { |object| object.public_send(self, *args, &block) }
end
end
(also uses public_send
instead of send
to prevent calling private methods, also caller
is already used by ruby so this was confusing)
For your example can be done a.map(&2.method(:+))
.
Arup-iMac:$ pry
[1] pry(main)> a = [1,3,5,7,9]
=> [1, 3, 5, 7, 9]
[2] pry(main)> a.map(&2.method(:+))
=> [3, 5, 7, 9, 11]
[3] pry(main)>
Here is how it works :-
[3] pry(main)> 2.method(:+)
=> #<Method: Fixnum#+>
[4] pry(main)> 2.method(:+).to_proc
=> #<Proc:0x000001030cb990 (lambda)>
[5] pry(main)> 2.method(:+).to_proc.call(1)
=> 3
2.method(:+)
gives a Method object. Then &
, on 2.method(:+)
, actually a call #to_proc method, which is making it a Proc
object. Then follow What do you call the &: operator in Ruby?.
As the post you linked to confirms, a.map(&:class)
is not a shorthand for a.map {|x| x.class}
but for a.map(&:class.to_proc)
.
This means that to_proc
is called on whatever follows the &
operator.
So you could give it directly a Proc
instead:
a.map(&(Proc.new {|x| x+2}))
I know that most probably this defeats the purpose of your question but I can't see any other way around it - it's not that you specify which method to be called, you just pass it something that responds to to_proc
.
There is another native option for enumerables which is pretty only for two arguments in my opinion. the class Enumerable
has the method with_object
which then returns another Enumerable
.
So you can call the &
operator for a method with each item and the object as arguments.
Example:
a = [1,3,5,7,9]
a.to_enum.with_object(2).map(&:+) # => [3, 5, 7, 9, 11]
In the case you want more arguments you should repeat the proccess but it's ugly in my opinion:
a = [1,3,5,7,9]
a.to_enum.with_object(2).map(&:+).to_enum.with_object(5).map(&:+) # => [8, 10, 12, 14, 16]
Instead of patching core classes yourself, as in the accepted answer, it's shorter and cleaner to use the functionality of the Facets gem:
require 'facets'
a = [1,3,5,7,9]
a.map &:+.(2)