Ruby 2.0.0はキーワード引数(KA)をサポートしており、純粋なRubyのコンテキストでこの機能の利点/ユースケースは何であるか、特にキーワードのマッチングを毎回行う必要があるためにパフォーマンスが低下することを考慮した場合はどうでしょうか。キーワード引数を持つメソッドが呼び出されたとき。
require 'benchmark'
def foo(a:1,b:2,c:3)
[a,b,c]
end
def bar(a,b,c)
[a,b,c]
end
number = 1000000
Benchmark.bm(4) do |bm|
bm.report("foo") { number.times { foo(a:7,b:8,c:9) } }
bm.report("bar") { number.times { bar(7,8,9) } }
end
# user system total real
# foo 2.797000 0.032000 2.829000 ( 2.906362)
# bar 0.234000 0.000000 0.234000 ( 0.250010)
キーワード引数には、誰も触れていないいくつかの明確な利点があります。
まず第一に、あなたは議論の順序に縛られていません。したがって、nil引数がある場合は、かなりきれいに見えることがあります。
def yo(sup, whats="good", dude="!")
# do your thing
end
yo("hey", nil, "?")
キーワード引数を使用する場合:
def yo(sup:, whats:"good", dude:"!")
# do your thing
end
yo(sup: "hey", dude: "?")
あるいは
yo(dude: "?", sup: "hey")
これにより、引数の順序を覚えておく必要がなくなります。ただし、デメリットは、引数の名前を覚えておく必要があることですが、それは多かれ少なかれ直感的である必要があります。
また、将来さらに多くの引数を取る必要がある可能性のあるメソッドがある場合。
def create_person(name:, age:, height:)
# make yourself some friends
end
あなたのシステムが突然人のお気に入りのキャンディーバーについて知りたがっている場合、または彼らが太りすぎである場合(彼らのお気に入りのキャンディーバーをあまりにも多く消費しているため)、どうしますか?シンプル:
def create_person(name:, age:, height:, favorite_candy:, overweight: true)
# make yourself some fat friends
end
キーワード引数の前には常にハッシュがありましたが、それは変数を抽出して割り当てるためのより多くの定型コードにつながりました。ボイラープレートコード==より多くのタイピング==より多くの潜在的なタイプミス==より少ない回数の素晴らしいRubyコード。
def old_way(name, opts={})
age = opts[:age]
height = opts[:height]
# all the benefits as before, more arthritis and headaches
end
1つの引数を取るメソッドを設定するだけで、変更する必要がほとんどない場合:
def say_full_name(first_name, last_name)
puts "#{first_name} #{last_name}"
end
次に、パフォーマンスへの影響が小さいため、キーワード引数は避ける必要があります。
KAはRuby全体のイノベーションであるため、2つの主な利点があります。
まとめ:
a = lambda { |name: "Leonardo", age: 67| [name, age] }
a.call # ⇒ ["Leonardo", 67]
a.call name: "Michelangelo", age: 88 # ⇒ ["Michelangelo", 88]
a.call name: "Schwarzenegger", alive: true # ⇒ ArgumentError: unknown keyword: alive
Ruby-2.2.0以降、キーワード引数を使用することによる非効率的な問題は問題ではなくなったようです。
機能#1044 速度の問題を修正し、 Ruby-2.2. でリリースされました:
月11月3日03:02:382014笹田耕一
- メソッド/ブロックパラメータフィッティングロジックを書き直して、キーワード引数/パラメータとスプラット引数を最適化します。 機能#1044 (詳細はこのチケットに記載されています)
あなたはこれをあなた自身で見ることができます(元の質問で与えられたのと同じコードを使用して):
(08:04:%) rvm use Ruby-2.0.0-p247
Using /Users/adam/.rvm/gems/Ruby-2.0.0-p247
(08:04:%) Ruby keyword_benchmarks.rb
user system total real
foo 1.390000 0.060000 1.450000 ( 1.451284)
bar 0.130000 0.000000 0.130000 ( 0.122344)
(08:04:%) rvm use Ruby-2.2.0
Using /Users/adam/.rvm/gems/Ruby-2.2.0
(08:04:%) Ruby keyword_benchmarks.rb
user system total real
foo 0.140000 0.000000 0.140000 ( 0.136194)
bar 0.110000 0.000000 0.110000 ( 0.116246)
キーワード引数を使用した場合のパフォーマンスの低下はごくわずかですが、読みやすさと位置の柔軟性の向上と引き換えに、許容できるトレードオフだと思います。
例えば
機能
def welcome_message(message, options={})
default_options = {name: 'hoge'}
options = default_options.merge(options)
"#{message}、#{options[:name]}"
end
書くことができます
def welcome_message(message, name: 'hoge')
"#{message}、#{name}"
end