Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Other Ruby Map Shorthand Notation

I am aware of the shorthand for map that looks like:

[1, 2, 3, 4].map(&:to_s) > ["1", "2", "3", "4"] 

I was told this is shorthand for:

[1, 2, 3, 4].map{|i| i.to_s} 

This makes perfect sense. My question is this: It seems there should be an easier way to write:

[1, 2, 3, 4].map{|x| f.call(x)}  

for some procedure f. I know the way I just typed isn't all that long to begin with, but I'd contend that neither is the previous example for which the shorthand exists. This example just seems like the complement to the first example: Rather than calling i's to_s method for every i, I wish to call f for every x.

Does such a shorthand exist?

like image 208
trh178 Avatar asked Jan 09 '12 18:01

trh178


People also ask

How do I use .map in Ruby?

The way the map method works in Ruby is, it takes an enumerable object, (i.e. the object you call it on), and a block. Then, for each of the elements in the enumerable, it executes the block, passing it the current element as an argument. The result of evaluating the block is then used to construct the resulting array.

What is the difference between map and each in Ruby?

Each is like a more primitive version of map… It gives you every element so you can work with it, but it doesn't collect the results. Each always returns the original, unchanged object. It returns a new array with the transformed elements.

Where do I get a map in Ruby?

The Map is obtained in Jubilife City, when visiting the Trainers' School.


1 Answers

Unfortunately this shorthand notation (which calls "Symbol#to_proc") does not have a way to pass arguments to the method or block being called, so you couldn't even do the following:

array_of_strings.map(&:include, 'l') #=> this would fail 

BUT, you are in luck because you don't actually need this shortcut to do what you are trying to do. The ampersand can convert a Proc or Lambda into a block, and vice-versa:

my_routine = Proc.new { |str| str.upcase } %w{ one two three }.map &my_routine #=> ['ONE', 'TWO', 'THREE'] 

Note the lack of the colon before my_routine. This is because we don't want to convert the :my_routine symbol into a proc by finding the method and calling .method on it, rather we want to convert the my_routine Proc into a block and pass it to map.

Knowing this, you can even map a native Ruby method:

%w{ one two three }.map &method(:p) 

The method method would take the p method and convert it into a Proc, and the & converts it into a block that gets passed to map. As a result, each item gets printed. This is the equivalent of this:

%w{ one two three }.map { |s| p s } 
like image 136
coreyward Avatar answered Sep 18 '22 23:09

coreyward