我试图缩短
values.map { |value| value.gsub!("\n", ' ') }
与
values.map(&:gsub!("\n", ' '))
但它给了我一个:
SyntaxError:
...csv_creator.rb:40: syntax error, unexpected '(', expecting ')'
values.map(&:gsub!("\n", ' '))
任何人都知道发生了什么?
答案 0 :(得分:3)
&:method
表示法使用#to_proc
方法,该方法能够将符号转换为Proc
个对象。如果需要为被调用的方法提供其他参数,则不能将其用作快捷方式。
有关#to_proc
的更长解释可以在单独的答案中找到:What does to_proc method mean?
答案 1 :(得分:3)
&:foo
可能被错误地视为&:
加foo
(类似" pretzel colon"加强了这种错误观点。但是这里没有调用方法foo
。 &:foo
实际上是&
加:foo
,后者是一个简单的符号。
调用方法时,&object
(没有:
)调用object.to_proc
(应该返回Proc
)并将返回的proc作为传递阻止参数到方法。
object
经常恰好是一个符号,而Symbol#to_proc
的实现在Ruby中看起来就像这样:(它实际用C语言编写)
class Symbol
def to_proc
proc { |object, *args| object.public_send(self, *args) }
end
end
所以这个:
method(&:symbol)
实际上变成了这个:
method { |object, *args| object.public_send(:symbol, *args) }
或者,如果method
没有产生多个值(例如map
),那么它只是:
method { |object| object.public_send(:symbol) }
显然,你不能通过符号传递额外的参数。
但是...... object
并不一定是一个符号。您可以使用另一个具有自定义to_proc
实现的类。让我们滥用Array
用于演示目的:
class Array
def to_proc
method, *args = self
proc { |obj| obj.public_send(method, *args) }
end
end
这个黑客会允许你写:
["foo\nbar", "baz\nqux"].map(&[:gsub, "\n", '-'])
#=> ["foo-bar", "baz-qux"]
答案 2 :(得分:1)
只是为了展示可以做的事情:你可以定义不带参数的String
方法。
class String
def replace_newlines!(replace = ' ')
gsub!("\n", replace)
end
def replace_newlines(replace = ' ')
gsub("\n", replace)
end
end
p new_values = values.map(&:replace_newlines)
#=> ["1 2", "a b"]
p values.each(&:replace_newlines!)
#=> ["1 2", "a b"]
可悲的是,refinements wouldn't work与to_proc
。
另一种可能性是定义新的Proc
,而无需修补猴子String
:
my_gsub = proc { |string| string.gsub("\n", ' ') }
p new_values = values.map(&my_gsub)
#=> ["1 2", "a b"]
请注意map
与!
方法一起使用时没有多大意义。你应该:
map
与gsub
each
使用gsub!