2013-02-25 35 views
10

Ruby 2.0.0支持關鍵字參數(KA),我想知道在純Ruby環境中該功能的優點/用例 - 尤其是當根據由於每次調用具有關鍵字參數的方法時需要執行的關鍵字匹配而導致性能損失。何時在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) 

回答

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 
+0

要添加到答案中,請在需要將參數分配給方法定義內的變量並避免自己編寫自定義代碼時使用它們。 – Kashyap 2013-02-25 08:17:50

+0

請不要欺騙我們。 'def welcome_message(message,options = {:name =>'hoge'}); 「#{message},#{options [:name]}」; end'是'welcome_message'的一行代碼。但是,這種方法的主要缺點是需要用'key_valid?'擴展'Hash'或希望傳遞的鍵是正確的。 KA方法可以準確指定允許哪些鍵。 – mudasobwa 2013-02-25 08:52:29

+1

@mudasobwa對我來說,你錯了;與你的功能,'WELCOME_MESSAGE( 「信息」,{:年齡=> 22})'不會顯示在結果沒有'hoge',但將使用'keyword'。你的函數爲整個散列設置一個默認值,而不是散列定義鍵的默認值。 – oldergod 2013-02-25 09:00:00

3

因爲KA是紅寶石範圍內的創新,我看到了兩個主要優點:

  • 將允許的參數限制在預定義的集合中,正如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 
10

關鍵字參數有幾個明顯的優勢,沒有人觸及。

首先你沒有耦合到參數的順序。因此,在一個情況下,你可能有一個無參數偶爾看起來會更加清晰:

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 

如果你是剛剛建立它有一個參數,並且很可能永遠不會有一個需要改變的方法:

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

然後關鍵字參數應儘量避免,因爲有一個小的性能擊中。

3

從ruby-2.2.0開始,使用關鍵字參數的低效率問題似乎不再成爲問題。

Feature #10440固定速度問題和被髮布在ruby-2.2.0

週一年11月3 3點02分38秒2014光一笹

  • 重寫方法/塊參數擬合邏輯優化關鍵字參數/參數和一個splat參數。 Feature #10440(詳細情況見本傳票中描述的)

你可以看到自己這一點(使用相同的代碼,在原來的問題給出):

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

目前仍然是一個極其微不足道的性能損失使用關鍵字參數,但我認爲這是一個可以接受的折衷方式,以提高可讀性和位置靈活性。