枚举器:带有两个参数的收集方法
我有这样的代码:
users = ["foo", "bar"]
users.collect { |item, value = []| value << {:name => item} }.flatten
这在 ruby-1.9.2 中像风一样工作:
=> [{:name=>"foo"}, {:name=>"bar"}]
但这在 ruby-1.8.7 中不起作用,因为它不喜欢收集两个参数:
SyntaxError: compile error
(irb):2: syntax error, unexpected '=', expecting '|'
users.collect { |item, value = []| value << {:name => item} }.flatten
阅读文档 这是真的,collect 不需要两个参数,但它在 ruby 中工作1.9.2.那么我是否遗漏了一些东西,我的 Array
/Enumerable
正在以某种奇怪的方式进行修补,或者文档是否错误?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
我认为你错过了一些东西。这就是你想要做的,它在 1.9 和 1.8 中都有效:
I think you are missing something. This is what you want to do, and it works in both 1.9 and 1.8:
1.8.7 并不是抱怨块获取两个参数,而是抱怨您尝试为第二个参数提供默认值。这个:
在 1.8.7 中解析得很好,但是,当然,它在运行时会失败,因为
value
是nil
。1.9 确实允许块参数使用默认值(见下文)。
所以不,文档没有错,您只是使用
collect
以一种奇怪的方式在 1.9.2 中工作,因为它允许块参数的默认值。无论如何,您对
collect
的使用有点复杂,并且可能没有按照您想象的那样做,您应该听Casper并只做一个简单的collect
:但是,如果您有
<<
的东西并且无论如何都想使用它,您可以使用inject
在 1.8.7 和 1.9.2 中:但这毫无意义的复杂性。
你激起了我的好奇心,所以我去 Ruby 解析器文件寻求权威参考。也许毫无意义的忙碌工作,但“无意义”和“糟糕”是不同的事情。
1.9.2-p180
parse.y
有以下内容:如果您稍微跟踪一下,您会发现
block_param
规则用于类似这样的事情:以及
do
/end
形式。然后从block_param
向下追踪到f_block_opt
,您将看到语法明确允许默认值的位置。OTOH,1.8.7-p248
parse.y
有这样的内容:block_var
中没有任何内容允许块参数使用默认值。tOROP
只是允许这两种形式:1.8.7 isn't complaining about the block getting two parameters, it is complaining about your attempt to provide a default value for the second parameter. This:
parses fine in 1.8.7 but, of course, it falls over at run time because
value
isnil
.1.9 does allow default values for block arguments (see below).
So no, the documentation isn't wrong, you're just using
collect
in a strange way that works in 1.9.2 because it allows default values for block arguments.Anyway, your using of
collect
is a bit convoluted and might not be doing quite what you think it is doing, you should listen to Casper and just do a simplecollect
:But, if you have a thing for
<<
and want to use it no matter what, you could useinject
in both 1.8.7 and 1.9.2:That is pointless complexity though.
You piqued my curiosity so I went to the Ruby parser files for an authoritative reference. Pointless busy work perhaps but "pointless" and "bad" are different things.
The 1.9.2-p180
parse.y
has these things:If you trace through it a bit, you'll see that the
block_param
rule is used for things like this:and the
do
/end
form as well. Then trace fromblock_param
down tof_block_opt
and you'll see where default values are explicitly allowed by the grammar.OTOH, The 1.8.7-p248
parse.y
has this:There is nothing in
block_var
that allows default values for block arguments. ThetOROP
is just there to allow both of these forms: