我在RailsCast中找到了这段代码:
def tag_names
@tag_names || tags.map(&:name).join(' ')
end
map(&:name)中的(&:name)是什么意思?
我在RailsCast中找到了这段代码:
def tag_names
@tag_names || tags.map(&:name).join(' ')
end
map(&:name)中的(&:name)是什么意思?
当前回答
它等价于
def tag_names
@tag_names || tags.map { |tag| tag.name }.join(' ')
end
其他回答
这里:name是指向标记对象的方法名的符号。 当我们将&:name传递给map时,它将把name作为一个proc对象。 简而言之,tags.map(&:name)充当:
tags.map do |tag|
tag.name
end
同时让我们也注意到& #to_proc魔法可以对任何类工作,而不仅仅是符号。很多ruby会选择在Array类上定义#to_proc:
class Array
def to_proc
proc { |receiver| receiver.send *self }
end
end
# And then...
[ 'Hello', 'Goodbye' ].map &[ :+, ' world!' ]
#=> ["Hello world!", "Goodbye world!"]
&的工作原理是在其操作数上发送to_proc消息,在上面的代码中,操作数属于Array类。因为我在Array上定义了#to_proc方法,所以这一行变成:
[ 'Hello', 'Goodbye' ].map { |receiver| receiver.send( :+, ' world!' ) }
如下所示:
def tag_names
if @tag_names
@tag_names
else
tags.map{ |t| t.name }.join(' ')
end
另一个很酷的简写,很多人不知道,是
array.each(&method(:foo))
这是一个简写
array.each { |element| foo(element) }
通过调用method(:foo),我们从self中获取了一个method对象,该对象表示它的foo方法,并使用&表示它有一个to_proc方法,该方法将它转换为Proc。
这是非常有用的,当你想做点自由风格的事情。一个例子是检查数组中是否有字符串等于字符串“foo”。有一种传统的方式:
["bar", "baz", "foo"].any? { |str| str == "foo" }
还有一种简单的方法:
["bar", "baz", "foo"].any?(&"foo".method(:==))
首选的方式应该是最易读的方式。
Ruby中没有&:操作符。你所看到的是&运算符应用于:符号。
在方法参数列表中,&操作符接受其操作数,如果还没有将其转换为Proc对象(通过对其调用to_proc),并将其传递给方法,就像使用了块一样。
my_proc = Proc.new{插入“foo”}
My_method_call (&my_proc) #是相同的: My_method_call {put "foo"}