我有这样的代码:
users = ["foo", "bar"]
users.collect { |item, value = []| value << {:name => item} }.flatten这就像ruby-1.9.2中的风一样工作:
=> [{:name=>"foo"}, {:name=>"bar"}]但这在ruby-1.8.7中不起作用,因为它不像collect获取两个参数:
SyntaxError: compile error
(irb):2: syntax error, unexpected '=', expecting '|'
users.collect { |item, value = []| value << {:name => item} }.flattenReading the documentation这是真的,collect不需要两个参数,但它在Ruby1.9.2中工作。那么,我是不是遗漏了什么,我的Array/Enumerable正在以某种奇怪的方式打补丁,还是文档有误?
发布于 2011-08-04 15:31:45
我想你漏掉了什么。这就是你想要做的,它在1.9和1.8中都有效:
users.collect { |i| { :name => i } }发布于 2011-08-04 15:36:42
1.8.7不是在抱怨代码块获取了两个参数,而是在抱怨你试图为第二个参数提供默认值。这一点:
users.collect { |item, value| value << {:name => item} }.flatten在1.8.7中可以很好地解析,但是,当然,它在运行时会崩溃,因为value是nil。
1.9允许块参数的默认值(见下文)。
所以,文档没有错,您只是以一种奇怪的方式使用了collect,这种方式在1.9.2中有效,因为它允许块参数的默认值。
不管怎么说,你对collect的使用有点复杂,而且可能不是你想象的那样,你应该听从Casper的建议,只做一个简单的collect
users.collect { |item| { :name => item } }但是,如果你对<<感兴趣,并且无论如何都想要使用它,你可以在1.8.7和1.9.2中使用inject:
users.inject([ ]) { |value, item| value << { :name => item } }不过,这是毫无意义的复杂性。
您激起了我的好奇心,所以我去Ruby解析器文件中寻找权威参考。也许没有意义的忙碌工作,但“无意义”和“糟糕”是不同的东西。
1.9.2-p180 parse.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-p248 parse.y有这样的特性:
opt_block_var : none
| '|' /* none */ '|'
| tOROP
| '|' block_var '|'block_var中没有允许块参数使用默认值的内容。tOROP就是为了支持这两种形式:
{ | | pancakes } # '|' /* none */ '|'
{ || pancakes } # tOROP, the logical "or" operator: ||https://stackoverflow.com/questions/6937316
复制相似问题