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

时间:2022-01-13 00:22:15

I found this code in a RailsCast:

我在RailsCast上发现了这个代码:

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

What does the (&:name) in map(&:name) mean?

在地图上(&:姓名)的意思是什么?

13 个解决方案

#1


467  

It's shorthand for tags.map(&:name.to_proc).join(' ')

这是简称tags.map(&:name.to_proc)。加入(' ')

If foo is an object with a to_proc method, then you can pass it to a method as &foo, which will call foo.to_proc and use that as the method's block.

如果foo是一个带有to_proc方法的对象,那么您可以将它传递给一个方法&foo,它将调用foo。to_proc并将其用作方法的块。

The Symbol#to_proc method was originally added by ActiveSupport but has been integrated into Ruby 1.8.7. This is its implementation:

符号#to_proc方法最初是由ActiveSupport添加的,但是已经集成到Ruby 1.8.7中。这是它的实现:

class Symbol
  def to_proc
    Proc.new do |obj, *args|
      obj.send self, *args
    end
  end
end

#2


158  

Another cool shorthand, unknown to many, is

另一个很酷的速记法,很多人都不知道

array.each(&method(:foo))

which is a shorthand for

哪个是速记

array.each { |element| foo(element) }

By calling method(:foo) we took a Method object from self that represents its foo method, and used the & to signify that it has a to_proc method that converts it into a Proc.

通过调用method(:foo),我们从self获取一个方法对象,该对象表示它的foo方法,并使用&表示它有一个to_proc方法,该方法将其转换为Proc。

This is very useful when you want to do things point-free style. An example is to check if there is any string in an array that is equal to the string "foo". There is the conventional way:

这是非常有用的,当你想做点*的风格。一个例子是检查数组中是否有任何字符串等于字符串“foo”。有一种传统的方式:

["bar", "baz", "foo"].any? { |str| str == "foo" }

And there is the point-free way:

有一种无点的方法:

["bar", "baz", "foo"].any?(&"foo".method(:==))

The preferred way should be the most readable one.

首选的方法应该是可读性最强的方法。

#3


69  

It's equivalent to

它等于

def tag_names
  @tag_names || tags.map { |tag| tag.name }.join(' ')
end

#4


38  

While let us also note that ampersand #to_proc magic can work with any class, not just Symbol. Many Rubyists choose to define #to_proc on Array class:

同时,让我们也注意到& #to_proc魔法可以用于任何类,而不仅仅是符号。许多Rubyists选择在数组类上定义#to_proc:

class Array
  def to_proc
    proc { |receiver| receiver.send *self }
  end
end

# And then...

[ 'Hello', 'Goodbye' ].map &[ :+, ' world!' ]
#=> ["Hello world!", "Goodbye world!"]

Ampersand & works by sending to_proc message on its operand, which, in the above code, is of Array class. And since I defined #to_proc method on Array, the line becomes:

&通过在其操作数上发送to_proc消息来工作,在上面的代码中,该操作数属于数组类。因为我在数组中定义了#to_proc方法,所以这一行变成:

[ 'Hello', 'Goodbye' ].map { |receiver| receiver.send( :+, ' world!' ) }

#5


35  

It's shorthand for tags.map { |tag| tag.name }.join(' ')

这是缩写标记。map {|tag| tag.name}。加入(' ')

#6


24  

tags.map(&:name)

is The same as

是一样的

tags.map{|tag| tag.name}

&:name just uses the symbol as the method name to be called.

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

#7


14  

Josh Lee's answer is almost correct except that the equivalent Ruby code should have been as follows.

Josh Lee的答案几乎是正确的,除了等效的Ruby代码应该如下所示。

class Symbol
  def to_proc
    Proc.new do |receiver|
      receiver.send self
    end
  end
end

not

class Symbol
  def to_proc
    Proc.new do |obj, *args|
      obj.send self, *args
    end
  end
end

With this code, when print [[1,'a'],[2,'b'],[3,'c']].map(&:first) is executed, Ruby splits the first input [1,'a'] into 1 and 'a' to give obj 1 and args* 'a' to cause an error as Fixnum object 1 does not have the method self (which is :first).

使用此代码,当打印[[[1,'a'],[2,'b'],[3,'c']].map(&:first)被执行时,Ruby将第一个输入[1,'a']分割为1和'a',以给obj 1和args* 'a,以造成一个错误,因为Fixnum object 1没有方法self。


When [[1,'a'],[2,'b'],[3,'c']].map(&:first) is executed;

当[[1,a),(2,' b '],[3,' c ']]. map(&:首先)执行;

  1. :first is a Symbol object, so when &:first is given to a map method as a parameter, Symbol#to_proc is invoked.

    :首先是一个符号对象,因此当&:first作为参数提供给map方法时,将调用符号#to_proc。

  2. map sends call message to :first.to_proc with parameter [1,'a'], e.g., :first.to_proc.call([1,'a']) is executed.

    map将调用消息发送到:first。带有参数[1,'a']的to_proc,例如:first.to_proc.call([1,'a'])被执行。

  3. to_proc procedure in Symbol class sends a send message to an array object ([1,'a']) with parameter (:first), e.g., [1,'a'].send(:first) is executed.

    符号类中的to_proc过程用参数(:first)向数组对象([1,'a'])发送消息,例如[1,'a'].send(:first)执行。

  4. iterates over the rest of the elements in [[1,'a'],[2,'b'],[3,'c']] object.

    遍历[1,'a'],[2,'b'],[3,'c']]]对象中的其余元素。

This is the same as executing [[1,'a'],[2,'b'],[3,'c']].map(|e| e.first) expression.

这是一样的执行[[1,' '],[2,' b '],[3,' c ']]。地图(| | e.first)表达式。

#8


7  

Two things are happening here, and it's important to understand both.

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

As described in other answers, the Symbol#to_proc method is being called.

正如在其他答案中描述的,符号#to_proc方法正在被调用。

But the reason to_proc is being called on the symbol is because it's being passed to map as a block argument. Placing & in front of an argument in a method call causes it to be passed this way. This is true for any Ruby method, not just map with symbols.

但是在符号上调用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)

The Symbol gets converted to a Proc because it's passed in as a block. We can show this by trying to pass a proc to .map without the ampersand:

符号被转换为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"]

Even though it doesn't need to be converted, the method won't know how to use it because it expects a block argument. Passing it with & gives .map the block it expects.

即使不需要转换,该方法也不知道如何使用它,因为它需要一个块参数。将它与& give .map一起传递并映射它期望的块。

#9


5  

(&:name) is short for (&:name.to_proc) it is same as tags.map{ |t| t.name }.join(' ')

(&:name)是(&:name.to_proc)的缩写,与标签相同。地图{ | t | t.name }。加入(' ')

to_proc is actually implemented in C

to_proc实际上是用C实现的

#10


2  

Although we have great answers already, looking through a perspective of a beginner I'd like to add the additional information:

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

What does map(&:name) mean in Ruby?

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

This means, that you are passing another method as parameter to the map function. (In reality you're passing a symbol that gets converted into a proc. But this isn't that important in this particular case).

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

What is important is that you have a method named name that will be used by the map method as an argument instead of the traditional block style.

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

#11


1  

Here :name is the symbol which point to the method name of tag object. When we pass &:name to map, it will treat name as a proc object. For short, tags.map(&:name) acts as:

这里:name是指向标记对象的方法名称的符号。当我们通过&:name to map时,它将把name作为proc对象。简言之,tag .map(&:name)的作用是:

tags.map do |tag|
  tag.name
end

#12


1  

it means

它的意思是

array.each(&:to_sym.to_proc)

#13


0  

It is same as below:

如下所示:

def tag_names
  if @tag_names
    @tag_names
  else
    tags.map{ |t| t.name }.join(' ')
end

#1


467  

It's shorthand for tags.map(&:name.to_proc).join(' ')

这是简称tags.map(&:name.to_proc)。加入(' ')

If foo is an object with a to_proc method, then you can pass it to a method as &foo, which will call foo.to_proc and use that as the method's block.

如果foo是一个带有to_proc方法的对象,那么您可以将它传递给一个方法&foo,它将调用foo。to_proc并将其用作方法的块。

The Symbol#to_proc method was originally added by ActiveSupport but has been integrated into Ruby 1.8.7. This is its implementation:

符号#to_proc方法最初是由ActiveSupport添加的,但是已经集成到Ruby 1.8.7中。这是它的实现:

class Symbol
  def to_proc
    Proc.new do |obj, *args|
      obj.send self, *args
    end
  end
end

#2


158  

Another cool shorthand, unknown to many, is

另一个很酷的速记法,很多人都不知道

array.each(&method(:foo))

which is a shorthand for

哪个是速记

array.each { |element| foo(element) }

By calling method(:foo) we took a Method object from self that represents its foo method, and used the & to signify that it has a to_proc method that converts it into a Proc.

通过调用method(:foo),我们从self获取一个方法对象,该对象表示它的foo方法,并使用&表示它有一个to_proc方法,该方法将其转换为Proc。

This is very useful when you want to do things point-free style. An example is to check if there is any string in an array that is equal to the string "foo". There is the conventional way:

这是非常有用的,当你想做点*的风格。一个例子是检查数组中是否有任何字符串等于字符串“foo”。有一种传统的方式:

["bar", "baz", "foo"].any? { |str| str == "foo" }

And there is the point-free way:

有一种无点的方法:

["bar", "baz", "foo"].any?(&"foo".method(:==))

The preferred way should be the most readable one.

首选的方法应该是可读性最强的方法。

#3


69  

It's equivalent to

它等于

def tag_names
  @tag_names || tags.map { |tag| tag.name }.join(' ')
end

#4


38  

While let us also note that ampersand #to_proc magic can work with any class, not just Symbol. Many Rubyists choose to define #to_proc on Array class:

同时,让我们也注意到& #to_proc魔法可以用于任何类,而不仅仅是符号。许多Rubyists选择在数组类上定义#to_proc:

class Array
  def to_proc
    proc { |receiver| receiver.send *self }
  end
end

# And then...

[ 'Hello', 'Goodbye' ].map &[ :+, ' world!' ]
#=> ["Hello world!", "Goodbye world!"]

Ampersand & works by sending to_proc message on its operand, which, in the above code, is of Array class. And since I defined #to_proc method on Array, the line becomes:

&通过在其操作数上发送to_proc消息来工作,在上面的代码中,该操作数属于数组类。因为我在数组中定义了#to_proc方法,所以这一行变成:

[ 'Hello', 'Goodbye' ].map { |receiver| receiver.send( :+, ' world!' ) }

#5


35  

It's shorthand for tags.map { |tag| tag.name }.join(' ')

这是缩写标记。map {|tag| tag.name}。加入(' ')

#6


24  

tags.map(&:name)

is The same as

是一样的

tags.map{|tag| tag.name}

&:name just uses the symbol as the method name to be called.

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

#7


14  

Josh Lee's answer is almost correct except that the equivalent Ruby code should have been as follows.

Josh Lee的答案几乎是正确的,除了等效的Ruby代码应该如下所示。

class Symbol
  def to_proc
    Proc.new do |receiver|
      receiver.send self
    end
  end
end

not

class Symbol
  def to_proc
    Proc.new do |obj, *args|
      obj.send self, *args
    end
  end
end

With this code, when print [[1,'a'],[2,'b'],[3,'c']].map(&:first) is executed, Ruby splits the first input [1,'a'] into 1 and 'a' to give obj 1 and args* 'a' to cause an error as Fixnum object 1 does not have the method self (which is :first).

使用此代码,当打印[[[1,'a'],[2,'b'],[3,'c']].map(&:first)被执行时,Ruby将第一个输入[1,'a']分割为1和'a',以给obj 1和args* 'a,以造成一个错误,因为Fixnum object 1没有方法self。


When [[1,'a'],[2,'b'],[3,'c']].map(&:first) is executed;

当[[1,a),(2,' b '],[3,' c ']]. map(&:首先)执行;

  1. :first is a Symbol object, so when &:first is given to a map method as a parameter, Symbol#to_proc is invoked.

    :首先是一个符号对象,因此当&:first作为参数提供给map方法时,将调用符号#to_proc。

  2. map sends call message to :first.to_proc with parameter [1,'a'], e.g., :first.to_proc.call([1,'a']) is executed.

    map将调用消息发送到:first。带有参数[1,'a']的to_proc,例如:first.to_proc.call([1,'a'])被执行。

  3. to_proc procedure in Symbol class sends a send message to an array object ([1,'a']) with parameter (:first), e.g., [1,'a'].send(:first) is executed.

    符号类中的to_proc过程用参数(:first)向数组对象([1,'a'])发送消息,例如[1,'a'].send(:first)执行。

  4. iterates over the rest of the elements in [[1,'a'],[2,'b'],[3,'c']] object.

    遍历[1,'a'],[2,'b'],[3,'c']]]对象中的其余元素。

This is the same as executing [[1,'a'],[2,'b'],[3,'c']].map(|e| e.first) expression.

这是一样的执行[[1,' '],[2,' b '],[3,' c ']]。地图(| | e.first)表达式。

#8


7  

Two things are happening here, and it's important to understand both.

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

As described in other answers, the Symbol#to_proc method is being called.

正如在其他答案中描述的,符号#to_proc方法正在被调用。

But the reason to_proc is being called on the symbol is because it's being passed to map as a block argument. Placing & in front of an argument in a method call causes it to be passed this way. This is true for any Ruby method, not just map with symbols.

但是在符号上调用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)

The Symbol gets converted to a Proc because it's passed in as a block. We can show this by trying to pass a proc to .map without the ampersand:

符号被转换为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"]

Even though it doesn't need to be converted, the method won't know how to use it because it expects a block argument. Passing it with & gives .map the block it expects.

即使不需要转换,该方法也不知道如何使用它,因为它需要一个块参数。将它与& give .map一起传递并映射它期望的块。

#9


5  

(&:name) is short for (&:name.to_proc) it is same as tags.map{ |t| t.name }.join(' ')

(&:name)是(&:name.to_proc)的缩写,与标签相同。地图{ | t | t.name }。加入(' ')

to_proc is actually implemented in C

to_proc实际上是用C实现的

#10


2  

Although we have great answers already, looking through a perspective of a beginner I'd like to add the additional information:

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

What does map(&:name) mean in Ruby?

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

This means, that you are passing another method as parameter to the map function. (In reality you're passing a symbol that gets converted into a proc. But this isn't that important in this particular case).

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

What is important is that you have a method named name that will be used by the map method as an argument instead of the traditional block style.

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

#11


1  

Here :name is the symbol which point to the method name of tag object. When we pass &:name to map, it will treat name as a proc object. For short, tags.map(&:name) acts as:

这里:name是指向标记对象的方法名称的符号。当我们通过&:name to map时,它将把name作为proc对象。简言之,tag .map(&:name)的作用是:

tags.map do |tag|
  tag.name
end

#12


1  

it means

它的意思是

array.each(&:to_sym.to_proc)

#13


0  

It is same as below:

如下所示:

def tag_names
  if @tag_names
    @tag_names
  else
    tags.map{ |t| t.name }.join(' ')
end