17

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)
4

4 に答える 4

16

キーワード引数には、誰も触れていない明確な利点がいくつかあります。

まず、引数の順序に結合されていません。したがって、引数が nil である場合がある場合は、よりきれいに見えます。

def print_greeting(name, message = "Hello")
  puts "#{message}, #{name}"
end

print_greeting("John Connor", "Hasta la vista") 

キーワード引数を使用する場合:

def print_greeting(message: "Hello", name:)
  puts "#{message}, #{name}"
end

print_greeting(message: "Hasta la vista", name: "John Connor") 

あるいは

print_greeting(name: "John Connor", message: "Goodbye")

引数の順序を覚えておく必要がなくなります。ただし、欠点は、引数の名前を覚えておく必要があることです。これは多かれ少なかれ直観的である必要があり、間違いなく、より慎重に検討されたメソッド シグネチャが得られます。

キーワード引数を使用するもう 1 つの利点は、将来追加の引数が必要になる可能性のあるメソッドがある場合です。

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

パフォーマンスがわずかに低下するため、キーワード引数は避ける必要があります。

于 2015-01-28T17:22:20.567 に答える
4

KA は ruby​​ 全体のイノベーションであるため、主な利点が 2 つあります。

  • Railsがassert_valid_keysで行うように、許可される引数を事前定義されたセットに制限します。
  • コード ブロック内で機能を使用します。

要約:

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
于 2013-02-25T09:17:24.610 に答える
1

例えば

機能

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
于 2013-02-25T08:15:30.397 に答える