Я нашел этот код в RailsCast :
def tag_names
@tag_names || tags.map(&:name).join(' ')
end
Что значит (&:name)
в map(&:name)
?
ruby
syntax
operators
parameter-passing
collimarco
источник
источник
Ответы:
Это сокращение для
tags.map(&:name.to_proc).join(' ')
Если
foo
это объект сto_proc
методом, то вы можете передать его методу as&foo
, который будет вызыватьfoo.to_proc
и использовать его как блок метода.Symbol#to_proc
Метод был первоначально добавлен ActiveSupport , но был интегрирован в Руби 1.8.7. Это его реализация:источник
&
, т.е.tags.map(&:name.to_proc).join(' ')
Еще одна классная стенография, неизвестная многим,
что является сокращением для
При вызове
method(:foo)
мы взялиMethod
объектself
, представляющий егоfoo
метод, и использовали его,&
чтобы показать, что у него естьto_proc
метод, который преобразует его вProc
.Это очень полезно, когда вы хотите делать вещи без стилей. Пример - проверить, есть ли какая-либо строка в массиве, равная этой строке
"foo"
. Есть общепринятый способ:И есть бессмысленный способ:
Предпочтительный способ должен быть наиболее читабельным.
источник
array.each{|e| foo(e)}
короче еще :-) +1 в любом случае&method
?[1,2,3].map(&Array.method(:new))
Это эквивалентно
источник
Хотя отметим также, что
#to_proc
магия амперсандов может работать с любым классом, а не только с Symbol. Многие Rubyists предпочитают определять#to_proc
в классе Array:Ampersand
&
работает, отправляяto_proc
сообщение на свой операнд, который в приведенном выше коде относится к классу Array. И так как я определил#to_proc
метод на массиве, строка становится:источник
Это сокращение для
tags.map { |tag| tag.name }.join(' ')
источник
&
оператор вызываетto_proc
свой операнд. Так что он не является специфичным для метода map и фактически работает с любым методом, который принимает блок и передает один или несколько аргументов в блок.такой же как
&:name
просто использует символ в качестве имени метода для вызова.источник
Ответ Джоша Ли является почти правильным, за исключением того, что эквивалентный код Ruby должен был выглядеть следующим образом.
не
С помощью этого кода, когда
print [[1,'a'],[2,'b'],[3,'c']].map(&:first)
выполняется, Ruby разбивает первый ввод[1,'a']
на 1 и 'a', чтобы датьobj
1 иargs*
'a', чтобы вызвать ошибку, так как объект Fixnum 1 не имеет метода self (который: first).Когда
[[1,'a'],[2,'b'],[3,'c']].map(&:first)
выполняется;:first
является объектом Symbol, поэтому когда&:first
он передается методу карты в качестве параметра, вызывается Symbol # to_proc.Карта отправляет сообщение о вызове: first.to_proc с параметром
[1,'a']
, например,:first.to_proc.call([1,'a'])
выполняется.Процедура to_proc в классе Symbol отправляет сообщение отправки в объект массива (
[1,'a']
) с параметром (: first), например,[1,'a'].send(:first)
выполняется.перебирает остальные элементы
[[1,'a'],[2,'b'],[3,'c']]
объекта.Это то же самое, что выполнение
[[1,'a'],[2,'b'],[3,'c']].map(|e| e.first)
выражения.источник
[1,2,3,4,5,6].inject(&:+)
инъекция ожидает лямбду с двумя параметрами (записку и предмет) и:+.to_proc
доставляет ее -Proc.new |obj, *args| { obj.send(self, *args) }
или{ |m, o| m.+(o) }
Здесь происходят две вещи, и важно понимать обе.
Как описано в других ответах,
Symbol#to_proc
метод вызывается.Но причина
to_proc
вызова символа состоит в том, что он передаетсяmap
как аргумент блока. Помещение&
перед аргументом в вызове метода приводит к тому, что он передается таким образом. Это верно для любого метода Ruby, не толькоmap
с символами.Symbol
Преобразуется кProc
потому , что она передается в качестве блока. Мы можем показать это, пытаясь передать процедуру.map
без амперсанда:Даже если его не нужно преобразовывать, метод не будет знать, как его использовать, поскольку он ожидает аргумент блока. Передача с ним
&
дает.map
ожидаемый блок.источник
(&: name) - это сокращение от (&: name.to_proc), оно совпадает с
tags.map{ |t| t.name }.join(' ')
to_proc фактически реализован в C
источник
карта (&: название) берет перечислимый объект (тэги в вашем случае) и запускает метод name для каждого элемента / тэга, выводя каждое возвращаемое значение из метода.
Это сокращение для
который возвращает массив имен элементов (тегов)
источник
Он в основном выполняет вызов метода
tag.name
для каждого тега в массиве.Это упрощенная рубиновая стенография.
источник
Хотя у нас уже есть отличные ответы, глядя на перспективу новичка, я хотел бы добавить дополнительную информацию:
Это означает, что вы передаете другой метод в качестве параметра функции map. (На самом деле вы передаете символ, который превращается в процесс. Но это не так важно в данном конкретном случае).
Важно то, что у вас есть
method
имя,name
которое будет использоваться методом карты в качестве аргумента вместо традиционногоblock
стиля.источник
Во-первых,
&:name
это ярлык для&:name.to_proc
, где:name.to_proc
возвращаетProc
(что-то похожее, но не идентичное лямбда-выражению), которое при вызове с объектом в качестве (первого) аргумента вызываетname
метод для этого объекта.Во-вторых, в то время как
&
indef foo(&block) ... end
преобразует блок, переданный вfoo
aProc
, он делает обратное при применении к aProc
.Таким образом,
&:name.to_proc
это блок , который принимает объект в качестве аргумента и вызываетname
метод на него, то есть{ |o| o.name }
.источник
Вот
:name
символ, который указывает на методname
объекта тега. Когда мы перейдем&:name
кmap
, он будет рассматриватьсяname
как объект proc. Для краткостиtags.map(&:name)
действует как:источник
это значит
источник
Это так же, как показано ниже:
источник