Есть ли идиоматический способ указать значения по умолчанию для необязательных параметров в Ruby?

Есть ли более краткий и идиоматический способ написания следующего кода, который используется для указания значений по умолчанию для необязательных параметров (в хэше params/options) для метода?

def initialize(params={})
  if params.has_key? :verbose
    @verbose = params[:verbose]
  else
    @verbose = true # this is the  default value
  end
end

Я хотел бы упростить это до чего-то вроде этого:

def initialize(params={})
  @verbose = params[:verbose] or true
end

который почти работает, за исключением того, что вам действительно нужно использовать has_key? :verbose в качестве условия, а не просто оценки params[:verbose], чтобы покрыть случаи, когда вы хотите указать значение "ложь" (т.е., если вы хотите передать :verbose => false в качестве аргумента в этом примере).

Я понимаю, что в этом простом примере я мог бы легко сделать:

def initialize(verbose=false)
  @verbose = verbose
end

но в моем реальном коде у меня фактически есть куча необязательных параметров (в дополнение к нескольким обязательным), и я хотел бы поместить необязательные параметры в хэш params, чтобы я мог легко указать (по имени) только несколько что я хочу, вместо того, чтобы перечислить их все по порядку (и, возможно, придется перечислить те, которые я на самом деле не хочу).

4 ответа

Решение

Распространенным примером является использование

def foo(options = {})
  options = { :default => :value }.merge(options)
end

Вы закончите с options будучи хэшем, содержащим переданные значения, с параметрами из вашего хэша по умолчанию, такими как те, которые не были предоставлены.

В Ruby 2.0.0 появилась новая функция аргументов ключевых слов

Ранее вам приходилось писать такой код:

def foo(options = {})
  options = {bar: 'bar'}.merge(options)
  puts "#{options[:bar]} #{options[:buz]}"
end

foo(buz: 'buz') # => 'bar buz'

Теперь это намного чище:

def foo(bar: 'bar', **options)
  puts "#{bar}, #{options}"
end

foo(buz: 'buz') # => 'bar buz'

Другой способ написать это, более кратко, было бы

def foo(options = {})
    options.reverse_merge! value1: true, value2: 100
end

Это устанавливает для параметров [: значение1] значение true (значение по умолчанию), если переданные параметры уже не содержат ключ: значение1. То же самое для:value2

Я думаю, что вы ищете это

params = { :verbose => true }.merge(params)
Другие вопросы по тегам