map(&:name) 在 Ruby 中意味着什么?
我在 a RailsCast 中找到了这段代码:
def tag_names
@tag_names || tags.map(&:name).join(' ')
end
( 的作用是什么
是什么意思?map(&:name)
中的 &:name)
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?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(17)
首先,
&:name
是&:name.to_proc
的快捷方式,其中:name.to_proc
返回一个Proc< /code> (类似于 lambda,但不完全相同),当使用对象作为(第一个)参数调用时,会调用该对象的
name
方法。其次, while
def foo(&block) ... end
中的&
将传递给foo
的块转换为Proc
,当应用于Proc
时,它会执行相反的操作。因此,
&:name.to_proc
是一个以对象作为参数并调用其name
方法的块,即{ |o| o.名称}
。First,
&:name
is a shortcut for&:name.to_proc
, where:name.to_proc
returns aProc
(something that is similar, but not identical to a lambda) that when called with an object as (first) argument, calls thename
method on that object.Second, while
&
indef foo(&block) ... end
converts a block passed tofoo
to aProc
, it does the opposite when applied to aProc
.Thus,
&:name.to_proc
is a block that takes an object as argument and calls thename
method on it, i. e.{ |o| o.name }
.尽管我们已经有了很好的答案,但从初学者的角度来看,我想添加额外的信息:
这意味着您正在将另一个方法作为参数传递给映射函数。
(实际上,您正在传递一个被转换为过程的符号。但这在这种特殊情况下并不那么重要)。
重要的是您有一个名为
name
的method
,map 方法将使用它作为参数,而不是传统的block
样式。Although we have great answers already, looking through a perspective of a beginner I'd like to add the additional information:
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).
What is important is that you have a
method
namedname
that will be used by the map method as an argument instead of the traditionalblock
style.它基本上对数组中的每个标签执行方法调用
tag.name
。这是一个简化的 Ruby 简写。
It basically execute the method call
tag.name
on each tags in the array.It is a simplified ruby shorthand.
Ruby 中没有 &: 运算符。您看到的是 &应用于 :symbol 的运算符。
在方法参数列表中, &运算符获取其操作数,如果尚未将其转换为 Proc 对象(通过对其调用 to_proc),并将其传递给方法,就像使用了块一样。
my_proc = Proc.new { puts "foo" }
my_method_call(&my_proc) # 等同于:
my_method_call { 放置“foo” }
There isn't a &: operator in Ruby. What you are seeing is the & operator applied to a :symbol.
In a method argument list, the & operator takes its operand, converts it to a Proc object if it isn't already (by calling to_proc on it) and passes it to the method as if a block had been used.
my_proc = Proc.new { puts "foo" }
my_method_call(&my_proc) # is identical to:
my_method_call { puts "foo" }
这里的
:name
是指向标签对象的方法name
的符号。当我们将
&:name
传递给map
时,它会将name
视为 proc 对象。简而言之,
tags.map(&:name)
的作用如下:Here
:name
is the symbol which point to the methodname
of tag object.When we pass
&:name
tomap
, it will treatname
as a proc object.For short,
tags.map(&:name)
acts as:这意味着
it means
与下面相同:
It is same as below:
它是
tags.map(&:name.to_proc).join(' ')
的简写如果
foo
是一个具有to_proc
方法的对象,然后您可以将其作为&foo
传递给方法,该方法将调用foo.to_proc
并将其用作方法的块。Symbol#to_proc
方法最初是由 ActiveSupport 添加的,但已集成到 Ruby 1.8.7 中。这是它的实现:It's shorthand for
tags.map(&:name.to_proc).join(' ')
If
foo
is an object with ato_proc
method, then you can pass it to a method as&foo
, which will callfoo.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:另一个很酷的简写方式,很多人都不知道,
的简写
它是通过调用
method(:foo)
我们从self
获取一个Method
对象 ,代表它的foo
方法,并使用&
表示它有一个to_proc
方法 将其转换为Proc
。当您想做无点风格的事情时,这非常有用。一个示例是检查数组中是否存在等于字符串
"foo"
的字符串。有传统的方式:还有无点的方式:
首选方式应该是最具可读性的方式。
Another cool shorthand, unknown to many, is
which is a shorthand for
By calling
method(:foo)
we took aMethod
object fromself
that represents itsfoo
method, and used the&
to signify that it has ato_proc
method that converts it into aProc
.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:And there is the point-free way:
The preferred way should be the most readable one.
它相当于
It's equivalent to
与相同
&:name
只是使用符号作为要调用的方法名称。is The same as
&:name
just uses the symbol as the method name to be called.同时我们还要注意,与号
#to_proc
魔法可以用于任何类,而不仅仅是 Symbol。许多 Rubyists 选择在 Array 类上定义#to_proc
:与号
&
通过在其操作数上发送to_proc
消息来工作,在上面的代码中,是Array类。由于我在 Array 上定义了#to_proc
方法,因此该行变为: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:Ampersand
&
works by sendingto_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:它是
tags.map { |tag| 的简写tag.name }.join(' ')
It's shorthand for
tags.map { |tag| tag.name }.join(' ')
这里发生了两件事,理解这两件事很重要。
正如其他答案中所述,正在调用
Symbol#to_proc
方法。但是在符号上调用
to_proc
的原因是因为它作为块参数传递给map
。将&
放在方法调用中的参数前面会导致它以这种方式传递。这对于任何 Ruby 方法都是如此,而不仅仅是带有符号的map
。Symbol
被转换为Proc
,因为它是作为块传入的。我们可以通过尝试将 proc 传递到不带&符号的.map
来展示这一点:即使不需要转换,该方法也不知道如何使用它,因为它需要一个块争论。使用
&
传递它会给出.map
它期望的块。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 tomap
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 justmap
with symbols.The
Symbol
gets converted to aProc
because it's passed in as a block. We can show this by trying to pass a proc to.map
without the ampersand: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.Josh Lee 的答案几乎是正确的,只是等效的 Ruby 代码应该如下所示。
没有
这段代码,当执行
print [[1,'a'],[2,'b'],[3,'c']].map(&:first)
时, Ruby 将第一个输入[1,'a']
拆分为 1 和 'a',将obj
1 和args*
'a' 提供给导致错误,因为 Fixnum 对象 1 没有 self 方法(即 :first)。当执行
[[1,'a'],[2,'b'],[3,'c']].map(&:first)
时;:first
是一个 Symbol 对象,因此当&:first
作为参数传递给 map 方法时,将调用 Symbol#to_proc。map 向 :first.to_proc 发送带有参数
[1,'a']
的调用消息,例如:first.to_proc.call([1,'a'])< /code> 被执行。
Symbol 类中的 to_proc 过程将发送消息发送到带有参数 (:first) 的数组对象 (
[1,'a']
),例如[1,'a' ].send(:first)
被执行。迭代
[[1,'a'],[2,'b'],[3,'c']]
对象中的其余元素。这与执行
[[1,'a'],[2,'b'],[3,'c']].map(|e| e.first)
表达式相同。Josh Lee's answer is almost correct except that the equivalent Ruby code should have been as follows.
not
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 giveobj
1 andargs*
'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;:first
is a Symbol object, so when&:first
is given to a map method as a parameter, Symbol#to_proc is invoked.map sends call message to :first.to_proc with parameter
[1,'a']
, e.g.,:first.to_proc.call([1,'a'])
is executed.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.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.(&:name) 是 (&:name.to_proc) 的缩写,它与
tags.map{ |t| 相同t.name }.join(' ')
to_proc 实际上是用 C 实现的
(&:name) is short for (&:name.to_proc) it is same as
tags.map{ |t| t.name }.join(' ')
to_proc is actually implemented in C
map(&:name) 接受一个可枚举对象(在您的情况下为标签)并为每个元素/标签运行 name 方法,输出该方法的每个返回值。
简写
它是返回元素(标签)名称数组的
map(&:name) takes an enumerable object (tags in your case) and runs the name method for each element/tag, outputting each returned value from the method.
It is a shorthand for
which returns the array of element(tag) names