Other Ruby Map Shorthand Notation
Asked Answered
U

2

42

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?

Unlace answered 9/1, 2012 at 18:55 Comment(1)
Is f an existing method you want to call?Mcwherter
S
69

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 }
Skyway answered 9/1, 2012 at 19:1 Comment(2)
While certainly true, I'm not convinced the OP will consider him/herself "lucky" to have to define the block separately in order to get a "shorter" map call.Mn
@DaveNewton I don't think you understand the question. It appears he already has an existing Proc or Lambda which he refers to as f in the question. He can get what he wants with array.map(&f), which is actually a character shorter than what he tried.Skyway
C
2

As of Ruby 2.7, numbered parameters (_1, _2, etc) are supported. This syntax can be cryptic, especially with more than one parameter, but it can be useful for simple situations.

[1, 2, 3, 4].map { f.call(_1) }
Circlet answered 21/4, 2022 at 15:13 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.