def hoge(a, b)
[a, b]
end
hoge(1) # ArgumentError: wrong number of arguments (1 for 2)
hoge(1, 2) #=> [1, 2]
hoge(1, 2, 3) # ArgumentError: wrong number of arguments (3 for 2)
# ちなみに
hoge 1, 2 #=> [1, 2]
# cがデフォルト引数
def hoge(a, b, c = 4)
[a, b, c]
end
hoge(1) # ArgumentError: wrong number of arguments (1 for 2..3)
hoge(1, 2) #=> [1, 2, 4] # cにはデフォルト値が入る
hoge(1, 2, 3) #=> [1, 2, 3] # デフォルト値が上書きされる
hoge(1, 2, 3, 4) # ArgumentError: wrong number of arguments (4 for 2..3)
def hoge(a, b, **args)
p a
p b
p args
end
hoge(1) # ArgumentError: wrong number of arguments (1 for 2+)
hoge(1, 2)
#=> 1
# 2
# []
hoge(1, 2, 3)
#=> 1
# 2
# [3]
hoge(1, 2, 3, "文字列", {x: 1, y: 2})
# => 1
# 2
# [3, "文字列", {:x=>1, :y=>2}]
def hoge(a, b = 3, *args)
#...
end
hoge(1) # a = 1, b = 3, args = []
hoge(1, 2) # a = 1, b = 2, args = []
hoge(1, 2, 3 , 4) # a = 1, b = 2, args = [3,4]
# これはできない(SymtaxError)
# 2引数目以降の引数をargsかbかどちらに入れればいいか判断がつかない
def hoge(a, *args, b = 3)
end
# でもこれはOK
def fuga(a, *args, b)
p a
p args
p b
end
fuga(1) # ArgumentError: wrong number of arguments (1 for 2+)
fuga(1, 2)
#=> 1
# []
# 2
fuga(1, 2, 3)
#=> 1
# [2]
# 3
def hoge(x: 1, y: 2)
p x
p y
end
hoge # x = 1, y = 2
hoge(x: 100) # x = 100, y = 2
hoge(y: 200) # x = 1 y = 200
hoge(x: 100, y: 200) # x = 100, y = 200
# (ほぼ)ハッシュと等価なので順序の入れ替えは自由,指定されていないものにデフォルト値が入る
hoge(y: 200, x: 100) # x = 200, y = 100
# ただし指定していないキーワードは入れられない
hoge(x: 100, y: 200, z: 300) # ArgumentError: unknown keyword: z
def hoge(x: 1, y: 2, z:)
#...
end
hoge(x: 10, y: 20, z: 30) # x = 10, y = 20, z = 30
# zを指定していないのでエラー
hoge(x: 10, y: 20) # ArgumentError: missing keyword: z
# 逆に言うとzさえ指定しいればOK
hoge(z: 30) # x = 1, y = 2, z = 30
def hoge(x: 1, y: 2, **opt)
p x
p y
p opt
end
hoge
#=> 1
# 2
# {}
# キーワード引数で指定されたもの以外のkey, valueの組がhashでoptに入る
hoge(x: 10, z: 30, u: 40)
#=> 10
# 2
# {:z=>30, :u=>40}
def hoge(&block)
if block_given?
block.call
else
"block is not given"
end
end
hoge #=> "block is not given"
# ブロックを渡せる
hoge { "block!!" } #=> "block!!"
block = Proc.new { "block" }
hoge(&block) #=> "block"
# ちなみに&blockは省略可で省略した場合内部ではyieldで呼び出す
def hoge
yield
end
hoge { "block" }
def hoge(a, b, c = 3, *args, d, e:, f: "7", **opts, &block)
p a
p b
p c
p args
p d
p e
p f
p opts
p block.call if block_given?
end
hoge # ArgumentError: missing keyword: e
hoge(
1, # a
2, # b
3, # d
e: "111" # e:
)
#=> 1
# 2
# 3
# []
# 3
# "111"
# "7"
# {}
hoge(10, 20, 30, 40, 50, 60, 70, a: "aaa", b: "bbb", c: "ccc", e: "eee") { "\(^o^)/" }
# a = 10
# b = 20
# c = 30
# args = [40, 50, 60]
# d = 70
# e = "eee"
# f = "7",
# opts = {
# a: "aaa",
# b: "bbb",
# c: "ccc"
# }
# block.call => "\(^o^)/"
宣言は下記の順で書く(下記以外でも入れ替え可能なものもあるが,混乱を招くだけなので)
- 通常の引数1
- デフォルト引数
- 可変長引数(1つのみ)
- キーワード引数(デフォルト値の有無は順序には関係ない)
- オプション引数(1つのみ)
- ブロック引数(1つのみ)
現実的には多くても3種類くらいにとどめておいたほうがいい. それ以上使う場合はクラス化やメソッドの細分化を検討したほうがいい(1メソッドにさせることは極力1roleに絞る)
- 通常の引数
- 必須パラメータで,メソッド名や引数名から何を渡せばよいか十分明確になっているもの.明確になっていないものはメソッドの見直しやキーワード引数の検討をしてみる
- デフォルト引数
- メソッドの実行に欠かせないパラメータではあるが,通常は広く認められたデフォルト値がありそれを使えば良いもの
- 可変長引数
- 呼び出し側で自然言語的に見やすくなるようなもの.(呼び出し側でArrayの1引数ではなく,あえて列挙したほうが視認性が上がるもの)
- 下位のメソッドに配列としてデリゲートするもの
- キーワード引数(デフォルト値つき)
- 必須ではないが,指定することによってそのメソッドのパラメータをカスタマイズできるもの (link_to method: :putなど)
- デフォルト引数よりかはよりカジュアルにオプショナルな設定を書いてよい
- デフォルト引数の有無によってメソッド内の処理を大きく変えない
- 呼び出し側でキーを指定したほうがわかりやすいと思われるものや自然言語として読みやすくなるもの
- 必須ではないが,指定することによってそのメソッドのパラメータをカスタマイズできるもの (link_to method: :putなど)
- キーワード引数(デフォルト値なし)
- 通常のパラメータよりも明示的に名称を指定したほうがわかりやすい場合
- より自然言語っぽくなる場合
- オプション引数 * 下位のメソッドにハッシュとしてデリゲートするもの
- ブロック引数
- blockを渡すときは明示的に書いています(blockという名前にとらわれず役割に適した変数名が付けられる && #callのメソッド名がより明示的なので)
自然言語的に美しくなることが善なのか?などはプロジェクトや周辺ライブラリの兼ね合いになるので, 一概には言えないが概ねこんな感じ. また下位にデリゲートしなければならないようなハッシュは巨大化している可能性があるので設計を見なおしたほうがよい場合が多いかもしれない