何时使用关键字参数也称为Ruby中的命名参数

时间:2013-02-25 08:08:24

标签: ruby named-parameters keyword-argument

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 个答案:

答案 0 :(得分:16)

关键字参数有一些明显优势,没人接触过。

首先,你没有加入参数的顺序。因此,如果您偶尔会有一个零参数,那么它看起来会更清晰:

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

在关键字参数之前总是存在哈希值,但这导致了更多的样板代码来提取和赋值变量。 Boilerplate代码==更多输入==更多潜在的错别字==少写一些令人敬畏的红宝石代码。

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

然后应避免使用关键字参数,因为性能影响很小。

答案 1 :(得分:4)

由于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

答案 2 :(得分:4)

使用关键字参数的低效问题似乎不再是ruby-2.2.0的问题。

Feature #10440解决了速度问题,已在ruby-2.2.0中发布:

  

Mon Nov 03 03:02:38 2014 Koichi Sasada

     
      
  • 重写方法/块参数拟合逻辑,以优化关键字参数/参数和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)

使用关键字args仍然存在极其微不足道的性能损失,但我认为这是一种可接受的权衡,以换取提高可读性和位置灵活性的好处。

答案 3 :(得分: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