In a map
, I can call a method on the passed-in value using the convenient &:
notation:
nums = (0..10).to_a
strs = nums.map(&:to_s)
Is there something similar for calling a function with the value passed in as the first argument?
nums = (0..10).to_a
nums.each(puts) # error!
Maps present information about the world in a simple, visual way. They teach about the world by showing sizes and shapes of countries, locations of features, and distances between places. Maps can show distributions of things over Earth, such as settlement patterns.
map insert() in C++ STL The map::insert() is a built-in function in C++ STL which is used to insert elements with a particular key in the map container. Parameters: The function accepts a pair that consists of a key and element which is to be inserted into the map container.
It's a new feature that introduced in ES6 and is called arrow function. The left part denotes the input of a function and the right part the output of that function.
Definition and Usage. map() creates a new array from calling a function for every array element. map() calls a function once for each element in an array. map() does not execute the function for empty elements. map() does not change the original array.
Disclaimer: This post is purely educational. nums.each {|n| puts n}
is really the only reasonable thing to write in a real project.
nums.map(&:to_s)
The existing short form works very simply. &
calls to_proc
on the symbol, and to_proc
on a symbol is defined like this.
class Symbol
def to_proc
Proc.new { |*args| args.shift.__send__(self, *args) }
end
end
Since this proc will start acting like a regular block that is passed into map, the *args
in this case is really each element we're iterating through. We take the first of args (since *
turns arguments into an array), and send self
to it, self
being the actual symbol, such as :to_s
. Remaining arguments are passed in. So it's like saying nums.map{ |*args| args.shift.__send__(:to_s, *args) }
.
nums.each(&:puts)
We could easily re-implement to_proc
to act differently. Here's a quick example.
class Symbol
def to_proc
Proc.new { |*args| __send__(self, *args) }
end
end
(1..10).each(&:print) # => 12345678910
Here instead of sending symbol name as a message to the element, we are just calling symbol as a method on the current context, and simply passing the iterated element as an argument to it.
So it's more like saying (1..10).each{|*args| __send__(:print, *args)}
.
nums.each(&method(:puts))
That said, as nash pointed out you could call nums.each(&method(:puts))
. What happens there is that you get an object that represents method puts
using ruby's method
method. So then &
calls .to_proc
on the method object, turning it into proc, which itself starts playing the role of the block passed into each
(or map
). The arguments passed into that proc (each element you're iterating) then become the arguments to that method. Neat.
xargs
In order to avoid overwriting standard behavior, we could hypothetically implement our own xargs feature, like in shell scripting. (Do not do this at home, too-clever is bad.)
class Symbol
def to_xargs
Proc.new{ |*args| __send__(self, *args) }
end
end
def xargs(sym)
sym.to_xargs
end
(1..10).each(&xargs(:print)) # prints 12345678910
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