我在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)是什么意思?
当前回答
它是tags.map(&:name.to_proc)的简写。加入(' ')
如果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
其他回答
这里发生了两件事,理解这两件事很重要。
正如在其他回答中所描述的,正在调用Symbol#to_proc方法。
但是符号上调用to_proc的原因是因为它被作为块参数传递给map。将&放在方法调用中的参数前面会导致它以这种方式传递。这适用于任何Ruby方法,而不仅仅是带有符号的映射。
def some_method(*args, &block)
puts "args: #{args.inspect}"
puts "block: #{block.inspect}"
end
some_method(:whatever)
# args: [:whatever]
# block: nil
some_method(&:whatever)
# args: []
# block: #<Proc:0x007fd23d010da8>
some_method(&"whatever")
# TypeError: wrong argument type String (expected Proc)
# (String doesn't respond to #to_proc)
Symbol被转换为Proc,因为它是作为块传入的。我们可以通过尝试传递一个不带&号的proc给.map来显示这一点:
arr = %w(apple banana)
reverse_upcase = proc { |i| i.reverse.upcase }
reverse_upcase.is_a?(Proc)
=> true
arr.map(reverse_upcase)
# ArgumentError: wrong number of arguments (1 for 0)
# (map expects 0 positional arguments and one block argument)
arr.map(&reverse_upcase)
=> ["ELPPA", "ANANAB"]
即使它不需要转换,方法也不知道如何使用它,因为它期望一个块参数。给它传递&给.map它所期望的块。
它等价于
def tag_names
@tag_names || tags.map { |tag| tag.name }.join(' ')
end
Ruby中没有&:操作符。你所看到的是&运算符应用于:符号。
在方法参数列表中,&操作符接受其操作数,如果还没有将其转换为Proc对象(通过对其调用to_proc),并将其传递给方法,就像使用了块一样。
my_proc = Proc.new{插入“foo”}
My_method_call (&my_proc) #是相同的: My_method_call {put "foo"}
tags.map(&:name)
是一样的
tags.map{|tag| tag.name}
&:name只是使用符号作为要调用的方法名。
另一个很酷的简写,很多人不知道,是
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(:==))
首选的方式应该是最易读的方式。