Сокращенное обозначение другой карты Ruby - PullRequest
22 голосов
/ 09 января 2012

Мне известно, что сокращение для карты выглядит так:

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

Мне сказали, что это сокращение для:

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

Это имеет смысл.У меня такой вопрос: кажется, что должен быть более простой способ написать:

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

для некоторой процедуры f.Я знаю, что способ, который я только что напечатал, не так уж и длинен для начала, но я бы сказал, что ни один из предыдущих примеров, для которых существует сокращение.Этот пример только кажется дополнением к первому примеру: вместо вызова метода to_s i для каждого i, я хочу вызвать f для каждого x.

Существует ли такое сокращение?

1 Ответ

44 голосов
/ 09 января 2012

К сожалению, в этой сокращенной записи (которая вызывает «Symbol # to_proc») нет способа передать аргументы вызываемому методу или блоку, поэтому вы даже не можете сделать следующее:

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

НО, вам повезло, потому что вам на самом деле не нужен этот ярлык , чтобы делать то, что вы пытаетесь сделать.Амперсанд может преобразовать Proc или Lambda в блок, и наоборот:

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

Обратите внимание на отсутствие двоеточия перед my_routine.Это связано с тем, что мы не хотим преобразовывать символ :my_routine в процесс путем нахождения метода и вызова для него .method, а хотим преобразовать my_routine Proc в блок и передать его в map.

Зная это, вы даже можете отобразить собственный метод Ruby:

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

Метод method будет принимать метод p и преобразовывать его в Proc, а & преобразует его в блок, который передается в map.В результате каждый элемент печатается.Это эквивалентно этому:

%w{ one two three }.map { |s| p s }
...