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

匿名 (未验证) 提交于 2019-12-03 08:41:19

问题:

I found this code in a RailsCast:

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

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

回答1:

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

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.

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

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


回答2:

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.

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:

["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:

It's equivalent to

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


回答4:

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:

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:

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


回答5:

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



回答6:

tags.map(&:name) 

is The same as

tags.map{|tag| tag.name} 

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



回答7:

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

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).


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

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

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

  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.

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

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



回答8:

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.

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.

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: #&0x007fd23d010da8>

&reverse_upcase

&



&:name&:name.to_proc



&:name





&:name&:name



&:to_sym.to_proc


标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!