我在RailsCast中找到了这段代码:

def tag_names
  @tag_names || tags.map(&:name).join(' ')
end

map(&:name)中的(&:name)是什么意思?


当前回答

Ruby中没有&:操作符。你所看到的是&运算符应用于:符号。

在方法参数列表中,&操作符接受其操作数,如果还没有将其转换为Proc对象(通过对其调用to_proc),并将其传递给方法,就像使用了块一样。

my_proc = Proc.new{插入“foo”}

My_method_call (&my_proc) #是相同的: My_method_call {put "foo"}

其他回答

它基本上在数组中的每个标签上执行方法调用tag.name。

它是一个简化的ruby简写。

tags.map(&:name)

是一样的

tags.map{|tag| tag.name}

&:name只是使用符号作为要调用的方法名。

Ruby中没有&:操作符。你所看到的是&运算符应用于:符号。

在方法参数列表中,&操作符接受其操作数,如果还没有将其转换为Proc对象(通过对其调用to_proc),并将其传递给方法,就像使用了块一样。

my_proc = Proc.new{插入“foo”}

My_method_call (&my_proc) #是相同的: My_method_call {put "foo"}

虽然我们已经有了很好的答案,但从初学者的角度来看,我想添加额外的信息:

map(&:name)在Ruby中是什么意思?

这意味着,您正在将另一个方法作为参数传递给map函数。 (实际上,您传递的是一个符号,该符号将被转换为proc。但在这种特殊情况下,这并不那么重要)。

重要的是,您有一个名为name的方法,它将被map方法用作参数,而不是传统的块样式。

这里发生了两件事,理解这两件事很重要。

正如在其他回答中所描述的,正在调用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它所期望的块。