我在a RailsCast中找到了此代码:
def tag_names
@tag_names || tags.map(&:name).join(' ')
end
(&:name)
中的map(&:name)
是什么意思?
[tags.map(&:name.to_proc).join(' ')
的简写
如果foo
是具有to_proc
方法的对象,则可以将其作为&foo
传递给方法,它将调用foo.to_proc
并将其用作方法的块。
Symbol#to_proc
方法最初是由ActiveSupport添加的,但已集成到Ruby 1.8.7中。这是它的实现:
class Symbol
def to_proc
Proc.new do |obj, *args|
obj.send self, *args
end
end
end
尽管我们已经有了很好的答案,但从初学者的角度来看,我想添加其他信息:
map(&:name)
接受一个可枚举的对象(在您的情况下为标签)并为每个元素/标签运行name方法,并从该方法输出每个返回的值。这里array.map { |element| element.name }
是指向标记对象的方法:name
的符号。当我们将name
传递给&:name
时,它将map
视为proc对象。简而言之,name
的作用是:
tags.map(&:name)
表示
tags.map do |tag|
tag.name
end
它基本上在数组中的每个标签上执行方法调用array.each(&:to_sym.to_proc)
。
这是简化的红宝石速记。
与以下相同:
tag.name
[首先,def tag_names
if @tag_names
@tag_names
else
tags.map{ |t| t.name }.join(' ')
end
是&:name
的快捷方式,其中&:name.to_proc
返回一个:name.to_proc
(与lambda类似但不相同的东西),当使用对象作为(第一个)参数调用时,该该对象的Proc
方法。
其次,虽然name
中的&
将传递给def foo(&block) ... end
的块转换为foo
,但是当应用于Proc
时却相反。
[另一种很酷的速记,很多人都不知道
array.each(&method(:foo))
这是]的简写>
array.each { |element| foo(element) }
通过调用
method(:foo)
,我们从Method
中获取了代表其self
方法的foo
对象,并使用&
表示它具有to_proc
method将其转换为[ C0]。
这在您要执行无点
样式时非常有用。一个示例是检查数组中是否有与字符串Proc
相等的字符串。有常规方法:"foo"
还有一种无意义的方式:
["bar", "baz", "foo"].any? { |str| str == "foo" }
首选方式应该是最易读的方式。
相当于
同时让我们注意到,&符def tag_names
@tag_names || tags.map { |tag| tag.name }.join(' ')
end
魔术可以适用于任何类别,而不仅限于Symbol。许多Rubyist选择在数组类上定义#to_proc
:
[[ 'Hello', 'Goodbye' ].map { |receiver| receiver.send( :+, ' world!' ) }
的简写
tags.map { |tag| tag.name }.join(' ')
Josh Lee的答案几乎是正确的,只是等效的Ruby代码应如下所示。
这里发生了两件事,理解两者都很重要。
[(&:name)是(&:name.to_proc)的缩写,它与.map
相同