1

私はこのコードを持っています:

users = ["foo", "bar"]
users.collect { |item, value = []| value << {:name => item} }.flatten

それはruby-1.9.2の風のように機能しています。

=> [{:name=>"foo"}, {:name=>"bar"}]

ただし、これはruby-1.8.7では機能しません。これは、収集が2つのパラメーターを取得することを好まないためです。

SyntaxError: compile error
(irb):2: syntax error, unexpected '=', expecting '|'
users.collect { |item, value = []| value << {:name => item} }.flatten

本当のドキュメントを読むと、collectは2つのパラメーターを期待していませんが、ruby1.9.2では機能しています。だから私は何かが足りないのですか、私のArray/Enumerableは奇妙な方法でパッチされていますか、それともドキュメントが間違っていますか?

4

2 に答える 2

5

何かが足りないと思います。これはあなたがやりたいことであり、1.9 と 1.8 の両方で機能します。

users.collect { |i| { :name => i } }
于 2011-08-04T07:31:45.290 に答える
2

1.8.7 は、ブロックが 2 つのパラメーターを取得することについて不平を言っているのではなく、2 番目のパラメーターにデフォルト値を提供しようとしていることに不平を言っています。これ:

users.collect { |item, value| value << {:name => item} }.flatten

は 1.8.7 で問題なく解析されますが、もちろん実行時にフォールオーバーしvalueますnil

1.9 では、ブロック引数の既定値を使用できます (以下を参照)。

いいえ、ドキュメントは間違っていませんcollect。ブロック引数のデフォルト値を許可するため、1.9.2 で動作する奇妙な方法で使用しているだけです。

とにかく、あなたの of の使用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: ||
于 2011-08-04T07:36:42.467 に答える