

[Drat! - Ruby has a Double Splat - Firmafon Developers
Blog](https://dev.firmafon.dk/blog/drat-ruby-has-a-double-splat/)

を見ました。

## 質問1. 仮引数の** と = {} の違いはなんでしょうか？

[code]

    def f(**options)
      p options #=> {:hoge=>"AAA", :foo=>"BBB"}
    end
    
    f hoge: "AAA", foo: "BBB"
    
[/code]

と

[code]

    def f(options = {})
      p options #=> {:hoge=>"AAA", :foo=>"BBB"}
    end
    
    f hoge: "AAA", foo: "BBB"
    
[/code]

の違いはなんでしょうか？

## 実際に試してみた例

[code]

    def f(options = {})
      p options #=> nil
    end
    
    f nil
    
[/code]

> （とくに問題なし）

**エラー**

[code]

    def f(**options)
      p options
    end
    
    f nil
    
[/code]

> `f': wrong number of arguments (1 for 0) (ArgumentError)

基準はわかりませんが、実引数に与えられた種類に応じてエラーにしてくれる場合が増えたということでしょうか？

  

## 質問2. ** と mergeメソッドとの違いは？

[code]

    options = { a: 'b' }
    hoge = { c: 'd', **options }
    p hoge #=> {:c=>"d", :a=>"b"}
    
    fuga =  { c: 'd'}.merge(options)
    p fuga #=> {:c=>"d", :a=>"b"}
    
[/code]

同じでしょうか？


CC BY-SA 3.0
2015-10-31T10:14:43.203
18273
2015-10-31T14:44:45.417
2020-06-17T08:14:45.997
-1
9008
question
ruby
RubyのDouble SplatとRubyの他の機能との違いについて


> 質問2. ** と mergeメソッドとの違いは？

ハッシュリテラルでは違いが分かりませんので、変数にします。

**{ **Hash, **Hash } の場合**

[code]

    irb> h1 = { a: 'b'}
    => {:a=>"b"}
    irb> h2 = { c: 'd'}
    => {:c=>"d"}
    irb> h12 = { **h1, **h2 }
    => {:a=>"b", :c=>"d"}
    irb> h1
    => {:a=>"b", :c=>"d"}
    irb> h2
    => {:c=>"d"}
    
[/code]

**merge メソッドの場合**

[code]

    irb> h1 = { a: 'b'}
    => {:a=>"b"}
    irb> h2 = { c: 'd'}
    => {:c=>"d"}
    irb> h12 = h1.merge(h2)
    => {:a=>"b", :c=>"d"}
    irb> h1
    => {:a=>"b"}
    irb> h2
    => {:c=>"d"}
    
[/code]

`{ **Hash, **Hash }` の場合は `h1` が書き変えられています。これは `Hash.merge!()` と同じです。

[code]

    irb> h12 = h1.merge!(h2)
    => {:a=>"b", :c=>"d"}
    irb> h1
    => {:a=>"b", :c=>"d"}
    irb> h2
    => {:c=>"d"}
    
[/code]

ソースコードでは以下の様になっていて、`Hash.merge()` の場合はコピーを渡している事が判るかと思います。

**ruby-2.6/hash.c**

[code]

    /*
     *  call-seq:
     *     hsh.merge(other_hash)
                :
    */
    static VALUE
    rb_hash_merge(VALUE hash1, VALUE hash2)
    {
        return rb_hash_update(rb_obj_dup(hash1), hash2);
                              ^^^^^^^^^^^^^^^^^
    }
    
    /*
     *  call-seq:
     *     hsh.merge!(other_hash)
                :
     */
    static VALUE
    rb_hash_update(VALUE hash1, VALUE hash2)
    {
        rb_hash_modify(hash1);
                :
    
[/code]


CC BY-SA 3.0
2015-10-31T14:44:45.417
18278
2015-10-31T14:44:45.417
18273
answer