Rubyの引数

# キーワード引数 (Keyword Arguments)
**仮引数の形**

```ruby
def f(hoge: "HOGE", foo: "FOO")
```
```rb
def f(hoge:, foo:)
```
**実引数の形**

```ruby
f(hoge: "AAA", foo:"BBB")
```

[Rubyist Magazine - Ruby 2.0.0 のキーワード引数](http://magazine.rubyist.net/?0041-200Special-kwarg)
[Ruby 2 Keyword Arguments](https://robots.thoughtbot.com/ruby-2-keyword-arguments)

```ruby
def f(hoge: "HOGE", foo: "FOO") #仮引数
  puts hoge
  puts foo
end

f(hoge: "AAA", foo:"BBB") #実引数
```

```rb
def f(hoge:, foo:) #仮引数
  puts hoge
  puts foo
end

f(hoge: "AAA", foo:"BBB") #実引数
```

実引数のところがちょっぴりObjective-Cぽい。
Objective-Cと違って順番を変えれるけどね。
実引数で**Hash**を渡しているのに、仮引数では、**Hashではなくなり**個別の変数に入っている（**与えたHashが個別の変数に分解されている**）。
いわゆる**名前付き引数**と思うんだけど違うのかなあ。

# Positional Arguments (日本語名は？）
一番普通のやつ。

```
def f(hoge, foo) #仮引数
  puts hoge
  puts foo
end

f("AAA", "BBB") #実引数
```

## Keyword arguments vs Positional arguments
Keyword argumentsのがコールしてるとこ読みやすいよねえ。
引数の順番も入れ替えれる。
まあ`VBA`のときから名前付き引数がスタンダートって感じよねえ。

#可変長引数 (英語名は？ Splat?)
[可変長引数 - うなの日記](http://unageanu.hatenablog.com/entry/20080325/1206451392)
**仮引数の形**

```ruby
def f(*hoge)
```

**実引数の形**

```ruby
f("AAA", "BBB")
```

実引数で与えたものを`*`で宣言した変数に**Array** にして入る。

```ruby
def f(*hoge)  #仮引数
  p hoge #=> ["AAA", "BBB"]
end

f("AAA", "BBB") #実引数
```

```ruby
def f(*hoge)  #仮引数
  p hoge #=> [{:hoge=>"AAA", :foo=>"BBB"}]
end

f(hoge: "AAA", foo:"BBB") #実引数

```

# Double Splat（日本語ではなんていうんだろう？）
[ruby - What does a double * (splat) operator do - Stack Overflow](http://stackoverflow.com/questions/18289152/what-does-a-double-splat-operator-do)
[Drat! - Ruby has a Double Splat - Firmafon Developers Blog](https://dev.firmafon.dk/blog/drat-ruby-has-a-double-splat/)
[Ruby and the double splat operator | Simplificator](http://blog.simplificator.com/2015/03/20/ruby-and-the-double-splat-operator/)

**仮引数の形**

```rb
def f(**options)
```

**実引数の形**

```rb
f hoge: "AAA", foo: "BBB"
```

`**`で宣言した変数に**Hash**で入る。

```rb

def f(**options) #仮引数
  p options #=> {:hoge=>"AAA", :foo=>"BBB"}
end

f hoge: "AAA", foo: "BBB" #実引数
```

んー

```rb
def f(options = {})
```
との違いがわからんぞ。　Double Splatの方が、実引数に変なのきたときにエラーにしてくれるって感じかな。
はじめは `options = {}`のシンタックスシュガーが`**options`と思ったんだが...

## なぜrailsのActiveRecordの引数で受け取れる形が多様なのか！？
[Module: ActiveRecord::FinderMethods — Documentation for rails (4.0.0)](http://www.rubydoc.info/docs/rails/4.0.0/ActiveRecord/FinderMethods#find-instance_method)

```rb
Person.find(1)       # returns the object for ID = 1
Person.find("1")     # returns the object for ID = 1
Person.find(1, 2, 6) # returns an array for objects with IDs in (1, 2, 6)
Person.find([7, 17]) # returns an array for objects with IDs in (7, 17)
Person.find([1])     # returns an array for the object with ID = 1
```

上記呼び出し例を見てもらえばわかるが、実引数に受け取れる形が多様すぎる。

どうして

```rb
Person.find(1, 2, 6)
Person.find([7, 17])
Person.find(1) # これは可変長引数(*のやつ)で受け取ってるので配列になるのは自明
```
こんな風に、配列でうけとったり、そうでなかったりできるのか！？

普通に自分で書くと、

```rb
def f(*args)
  p args #=> [[1, 2]]
end

f [1,2]
```
配列の入れ子になってしまう...

RoRのソースを読み進めると...

```rb
    def find_with_ids(*ids)
      raise UnknownPrimaryKey.new(@klass) if primary_key.nil?

      expects_array = ids.first.kind_of?(Array)
      return ids.first if expects_array && ids.first.empty?

      ids = ids.flatten.compact.uniq

      case ids.size
```

**発見！！**

```
ids = ids.flatten.compact.uniq
```
秘密はここと見た！

```rb
def f(*args)
  p args.flatten.compact.uniq #=> [1,2]
end

f [1,2]
```
ほらね！

## 実引数でHash渡してるのに仮引数*args
実引数で**Hash**渡してるのに仮引数`*args`になってるメソッドがちょいちょいある気がする。簡単にすると以下のように`*args`で**Array**になったやつを**Hash**に戻してた

```rb
def f(*args)
  p args #=> [{:hoge=>"AAA", :foo=>"BBB"}]
  other_f(*args)
end

def other_f(args)
  p args #=> {:hoge=>"AAA", :foo=>"BBB"}
end

f hoge: "AAA", foo: "BBB"
```

[Ruby - 可変長引数を引き回す - Qiita](http://qiita.com/t3kot3ko/items/ba3ce3a9fa13e8c8045c)
[Ruby覚え書き - Qiita](http://qiita.com/ftakao2007/items/bed2102ab17ea59e0f46)

可変長引数を使い回すやつの応用と思われる。

> - 配列の展開
>  - 実引数の頭に「*」をつけると配列を複数の引数として渡す事ができる
>  - 配列をメソッド呼び出しの引数リストとして渡したいときに便利


**参考までに**

```rb
def f(*args)
  p args #=> [{:hoge=>"AAA", :foo=>"BBB"}]
  other_f(*args)
end

def other_f(*args)
  p args #=> [{:hoge=>"AAA", :foo=>"BBB"}]
end

f hoge: "AAA", foo: "BBB"
```