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