準情報推測のビット:doublesplatを使用したメソッド呼び出しでは、doublesplatの引数を既存のキーワード引数とマージし、最後の引数にハッシュとして挿入します。リテラル空のハッシュを使用すると、コンパイラは、キーワードが存在しないことを確認することができ、およびハッシュの作成をスキップすることができます
puts RubyVM::InstructionSequence.compile("b = {}; a(**{})").disasm
== disasm: #<ISeq:<compiled>@<compiled>>================================
local table (size: 2, argc: 0 [opts: 0, rest: -1, post: 0, block: -1, kw: [email protected], kwrest: -1])
[ 2] b
0000 trace 1 ( 1)
0002 newhash 0
0004 setlocal_OP__WC__0 2
0006 putself
0007 opt_send_without_block <callinfo!mid:a, argc:0, FCALL|ARGS_SIMPLE>, <callcache>
0010 leave
あなたがいる限り、キーワードの総数は予想通りゼロであるのと同じ結果が得られます。このように、これらの2つは同じようにコンパイル:変数のハッシュ(つまり空であることを起こる)で
a()
a(**{})
を、この仮定を行うことができず、マージが常にハッシュ引数を生成する、と呼ばれる:
puts RubyVM::InstructionSequence.compile("b = {}; a(**b)").disasm
== disasm: #<ISeq:<compiled>@<compiled>>================================
local table (size: 2, argc: 0 [opts: 0, rest: -1, post: 0, block: -1, kw: [email protected], kwrest: -1])
[ 2] b
0000 trace 1 ( 1)
0002 newhash 0
0004 setlocal_OP__WC__0 2
0006 putself
0007 putspecialobject 1
0009 getlocal_OP__WC__0 2
0011 opt_send_without_block <callinfo!mid:core#hash_merge_kwd, argc:1, ARGS_SIMPLE>, <callcache>
0014 opt_send_without_block <callinfo!mid:dup, argc:0, ARGS_SIMPLE>, <callcache>
0017 opt_send_without_block <callinfo!mid:a, argc:1, FCALL|ARGS_SIMPLE>, <callcache>
0020 leave
だから、私は2.2.2が無駄と見なすいくつかの最適化コードを**{}
と追加し、余分なコードを生成することをスキップしていると思います。
あなたは常にキーワードの残りの部分を収集するためにあなたの方法を定義する場合、送信者がそれに合格しなかった場合でも、ハッシュが作成されるように、それは、中断されません。
def a(**x); p x; end
a() # works, x is {} - hash supplied by VM at receiver
a(**b) # works, x is {} - hash supplied by sender as b.merge({})
a(**{}) # works, x is {} - hash supplied by VM at receiver, **{} ignored
a(b, **{}) # works, x is {} - hash supplied by sender, **{} ignored
a({}, **{}) # works, x is {} - hash supplied by sender, **{} ignored
a(b, **b) # works, x is {} - hash supplied by sender as b.merge(b)
a({}, **b) # works, x is {} - hash supplied by sender as b.merge({})
あなたはルビーのどのバージョンランニング? – philomory
@philomory:2.3.1(これは出力にあります:p) – Amadan
驚いたことに、これは2.1.3,2.2.0では問題なく動作しますが、2.2.2では失敗します。それ以前のバージョンでは、 'a(** {}) 'でも例外をスローします。私はこれについての証拠は何も見当たりませんので、バグだと思います。 – prasann