1.8.7 并没有抱怨块获取两个参数,而是抱怨您尝试为第二个参数提供默认值。这:
users.collect { |item, value| value << {:name => item} }.flatten
在 1.8.7 中解析得很好,但是当然,它在运行时会崩溃,因为value
is nil
.
1.9 确实允许块参数的默认值(见下文)。
所以不,文档没有错,你只是collect
在以一种奇怪的方式使用 1.9.2,因为它允许块参数的默认值。
无论如何,你的使用collect
有点复杂,可能没有做你认为它正在做的事情,你应该听 Casper 并做一个简单的collect
:
users.collect { |item| { :name => item } }
但是,如果你有一个东西<<
并且无论如何都想使用它,你可以inject
在 1.8.7 和 1.9.2 中使用:
users.inject([ ]) { |value, item| value << { :name => item } }
不过,那是毫无意义的复杂性。
你激起了我的好奇心,所以我去 Ruby 解析器文件寻求权威参考。忙碌的工作也许毫无意义,但“无意义”和“糟糕”是不同的东西。
1.9.2-p180parse.y
有这些东西:
block_param : f_arg ',' f_block_optarg ',' f_rest_arg opt_f_block_arg
| f_arg ',' f_block_optarg ',' f_rest_arg ',' f_arg opt_f_block_arg
| f_arg ',' f_block_optarg opt_f_block_arg
/* ... */
f_block_optarg : f_block_opt
f_block_opt : tIDENTIFIER '=' primary_value
如果您稍微跟踪一下,您会发现该block_param
规则用于以下情况:
{ |eggs| ... }
{ |two_cent, stamp| ... }
{ |where_is, pancakes = 'house'| ... }
以及do
/end
形式。block_param
然后从下往上追溯f_block_opt
,您将看到语法明确允许默认值的位置。
OTOH,1.8.7-p248parse.y
有这个:
opt_block_var : none
| '|' /* none */ '|'
| tOROP
| '|' block_var '|'
没有任何block_var
内容允许块参数的默认值。tOROP
只是允许这两种形式:
{ | | pancakes } # '|' /* none */ '|'
{ || pancakes } # tOROP, the logical "or" operator: ||