col*_*rco 483 ruby syntax operators parameter-passing
我在RailsCast中找到了这段代码:
def tag_names
@tag_names || tags.map(&:name).join(' ')
end
Run Code Online (Sandbox Code Playgroud)
什么是(&:name)
中map(&:name)
意味着什么?
Jos*_*Lee 510
这是简写 tags.map(&:name.to_proc).join(' ')
如果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
Run Code Online (Sandbox Code Playgroud)
Ger*_*rry 171
另一个很酷的简写,很多人都不知道
array.each(&method(:foo))
Run Code Online (Sandbox Code Playgroud)
这是一个简写
array.each { |element| foo(element) }
Run Code Online (Sandbox Code Playgroud)
通过调用method(:foo)
我们Method
从中获取了一个self
表示其foo
方法的对象,并使用它&
来表示它有一个to_proc
方法将其转换为Proc
.
当你想做无点风格的事情时,这非常有用.一个示例是检查数组中是否有与字符串相等的字符串"foo"
.有传统方式:
["bar", "baz", "foo"].any? { |str| str == "foo" }
Run Code Online (Sandbox Code Playgroud)
并且有无点的方式:
["bar", "baz", "foo"].any?(&"foo".method(:==))
Run Code Online (Sandbox Code Playgroud)
首选方式应该是最易读的方法.
Sop*_*ert 76
它相当于
def tag_names
@tag_names || tags.map { |tag| tag.name }.join(' ')
end
Run Code Online (Sandbox Code Playgroud)
Bor*_*cky 44
我们还要注意,&符号#to_proc
魔法可以适用于任何类,而不仅仅是符号.许多Rubyist选择#to_proc
在Array类上定义:
class Array
def to_proc
proc { |receiver| receiver.send *self }
end
end
# And then...
[ 'Hello', 'Goodbye' ].map &[ :+, ' world!' ]
#=> ["Hello world!", "Goodbye world!"]
Run Code Online (Sandbox Code Playgroud)
Ampersand &
通过to_proc
在其操作数上发送消息来工作,在上面的代码中,该操作数是Array类.由于我#to_proc
在Array上定义了方法,因此该行变为:
[ 'Hello', 'Goodbye' ].map { |receiver| receiver.send( :+, ' world!' ) }
Run Code Online (Sandbox Code Playgroud)
Oli*_* N. 38
这是简写 tags.map { |tag| tag.name }.join(' ')
Alb*_*ing 34
tags.map(&:name)
Run Code Online (Sandbox Code Playgroud)
是相同的
tags.map{|tag| tag.name}
Run Code Online (Sandbox Code Playgroud)
&:name
只需使用符号作为要调用的方法名称.
pro*_*eek 14
Josh Lee的答案几乎是正确的,除了等效的Ruby代码应该如下.
class Symbol
def to_proc
Proc.new do |receiver|
receiver.send self
end
end
end
Run Code Online (Sandbox Code Playgroud)
不
class Symbol
def to_proc
Proc.new do |obj, *args|
obj.send self, *args
end
end
end
Run Code Online (Sandbox Code Playgroud)
与此代码,当print [[1,'a'],[2,'b'],[3,'c']].map(&:first)
被执行时,红宝石分割第一输入[1,'a']
到1和"a",得到obj
1和args*
"a"到引起错误作为Fixnum对象物1不具有自我方法(其为:第一).
什么时候[[1,'a'],[2,'b'],[3,'c']].map(&:first)
执行;
:first
是一个Symbol对象,因此当&:first
将map方法作为参数赋予时,将调用Symbol#to_proc.
map将调用消息发送到:first.to_proc with parameter [1,'a']
,例如,:first.to_proc.call([1,'a'])
执行.
Symbol类中的to_proc过程[1,'a']
使用参数(:first)向数组对象()发送发送消息,例如,[1,'a'].send(:first)
执行.
迭代[[1,'a'],[2,'b'],[3,'c']]
对象中的其余元素.
这与执行[[1,'a'],[2,'b'],[3,'c']].map(|e| e.first)
表达式相同.
dev*_*ppy 11
这里发生了两件事情,理解两者都很重要.
如其他答案中所述,Symbol#to_proc
正在调用该方法.
但是在to_proc
符号上调用的原因是因为它被map
作为块参数传递给它.放置&
在方法调用中的参数前面会导致它以这种方式传递.对于任何Ruby方法都是如此,而不仅仅是map
符号.
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)
Run Code Online (Sandbox Code Playgroud)
将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"]
Run Code Online (Sandbox Code Playgroud)
即使它不需要转换,该方法也不会知道如何使用它,因为它需要一个块参数.传递它&
给出.map
了它期望的块.
小智 5
map(&:name)接受一个可枚举对象(在您的情况下为标签)并为每个元素/标签运行 name 方法,输出该方法的每个返回值。
它是一个简写
array.map { |element| element.name }
Run Code Online (Sandbox Code Playgroud)
它返回元素(标签)名称的数组
First,&:name
是 的快捷方式&:name.to_proc
,其中:name.to_proc
返回一个Proc
(与 lambda 类似但不相同的东西),当使用对象作为(第一个)参数调用时,调用name
该对象上的方法。
其次,虽然&
indef foo(&block) ... end
将传递给 a 的块转换foo
为 a Proc
,但应用于 a 时,它会执行相反的操作Proc
。
因此,&:name.to_proc
是一个以对象作为参数并调用name
其方法的块,即{ |o| o.name }
。
归档时间: |
|
查看次数: |
120152 次 |
最近记录: |