2013-02-25 10 views
10

Ruby 2.0.0 unterstützt Schlüsselwort Argumente (KA) und ich frage mich, was die Vorteile/Use-Cases von diesem Feature im Zusammenhang mit reinem Ruby, vor allem im Hinblick auf die Leistungseinbußen aufgrund des Keyword-Abgleichs, der jedes Mal ausgeführt werden muss, wenn eine Methode mit Schlüsselwortargumenten aufgerufen wird.Wann Schlüsselwort Argumente aka benannte Parameter in 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) 

Antwort

1

Zum Beispiel

Eine Funktion

def welcome_message(message, options={}) 
    default_options = {name: 'hoge'} 
    options = default_options.merge(options) 

    "#{message}、#{options[:name]}" 
end 

geschrieben werden konnte

def welcome_message(message, name: 'hoge') 
    "#{message}、#{name}" 
end 
+0

Um die Antwort hinzuzufügen, verwenden Sie sie, wenn Sie die Argumente den Variablen innerhalb Ihrer Methodendefinition zuweisen müssen, und vermeiden Sie es, benutzerdefinierten Code selbst zu schreiben. – Kashyap

+0

Bitte betrüge uns nicht. 'def welcome_message (Nachricht, Optionen = {: name => 'hoge'}); "# {Nachricht}, # {Optionen [: Name]}"; end 'ist der One-Liner für 'welcome_message'. Der Hauptnachteil dieses Ansatzes besteht jedoch darin, dass man 'Hash' um' 'key_valid?' 'Erweitern oder hoffen muss, dass die übergebenen Schlüssel korrekt sind. Mit der KA-Methode können Sie genau festlegen, welche Schlüssel zulässig sind. – mudasobwa

+1

@mudasobwa Scheint mir, du liegst falsch; Mit Ihrer Funktion wird 'welcome_message (" message ", {: age => 22})' im Ergebnis kein 'hoge' anzeigen, sondern das' keyword'. Sie stellen einen Standardwert für den gesamten Hash ein, keinen Standardwert für einen definierten Schlüssel des Hash. – oldergod

3

Seit KA Rubin weite Innovation, sehe ich zwei wesentliche Vorteile:

  • Begrenzen erlaubte Argumente zu einer vordefinierten Menge, wie Rails mit assert_valid_keys;
  • Verwenden Sie die Funktion in Codeblöcken.

Das Resümee:

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 
10

Schlüsselwort Argumente haben einige deutliche Vorteile niemand berührt hat.

Zunächst einmal sind Sie nicht an die Reihenfolge der Argumente gekoppelt. So in einem Fall, in dem Sie ein Null-Argument haben könnten gelegentlich sieht es viel sauberer:

def yo(sup, whats="good", dude="!") 
    # do your thing 
end 

yo("hey", nil, "?") 

wenn Sie Keyword-Argumente verwenden:

def yo(sup:, whats:"good", dude:"!") 
    # do your thing 
end 

yo(sup: "hey", dude: "?") 

oder sogar

yo(dude: "?", sup: "hey") 

Es entfernt die müssen sich an die Reihenfolge der Argumente erinnern. Der Nachteil ist jedoch, dass Sie sich den Namen des Arguments merken müssen, aber das sollte mehr oder weniger intuitiv sein.

Auch, wenn Sie eine Methode haben, die möglicherweise in der Zukunft mehr Argumente brauchen könnte.

def create_person(name:, age:, height:) 
    # make yourself some friends 
end 

was, wenn Ihr System ganz plötzlich will über eine Person, die Lieblingsschokoriegel wissen, oder wenn sie übergewichtig sind (zu viele ihrer Lieblings-Schokoriegel raubend), wie Sie das tun würde? Ganz einfach:

def create_person(name:, age:, height:, favorite_candy:, overweight: true) 
    # make yourself some fat friends 
end 

Vor Stichwort Argumente gab es immer die Hash, aber das zu viel Standardcode führte zu extrahieren und Variablen zuweisen. Boilerplate Code == mehr tippen == mehr potentielle Tippfehler == weniger Zeiten schreiben super Ruby Code.

def old_way(name, opts={}) 
    age = opts[:age] 
    height = opts[:height] 
    # all the benefits as before, more arthritis and headaches 
end 

Wenn Sie nur eine Methode einrichten, die ein Argument und wird höchstwahrscheinlich nie eine Notwendigkeit, zu ändern:

def say_full_name(first_name, last_name) 
    puts "#{first_name} #{last_name}" 
end 

Dann Schlüsselwort Argumente sollten vermieden werden, da es eine kleine Leistung schlagen.

3

Das Ineffizienzproblem der Verwendung von Schlüsselwortargumenten scheint ab ruby-2.2.0 kein Problem mehr zu sein.

Feature #10440 die Geschwindigkeit Problem behoben und wurde in ruby-2.2.0 freigegeben:

Mo 3. November 2014 03.02.38 Koichi Sasada

  • Rewrite-Methode/Blockparameteranpassung Logik zu optimieren Schlüsselwort Argumente/Parameter und ein Splat-Argument. Feature #10440 (Einzelheiten sind in dieser Karte beschrieben)

du selbst sehen können (mit dem gleichen Code wie in der ursprünglichen Frage gegeben):

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

Es gibt immer noch eine extrem vernachlässigbaren Leistungseinbuße Für die Verwendung von Keyword-Argumenten, aber ich denke, es ist ein akzeptabler Kompromiss im Austausch für den Vorteil der erhöhten Lesbarkeit und Positionsflexibilität.