Подтвердить что ты не робот

Могу ли я потребовать именованные параметры в Ruby 2.x?

Ruby 2.0 добавляет именованные параметры, например:

def say(greeting: 'hi')
  puts greeting
end

say                     # => puts 'hi'
say(greeting: 'howdy')  # => puts 'howdy'

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

4b9b3361

Ответ 1

В Ruby 2.0.0 нет конкретного пути, но вы можете сделать это Ruby 2.1.0 с синтаксисом вроде def foo(a:, b:) ...

В Ruby 2.0.x вы можете применить его, поставив любое выражение, создающее исключение, например:

def say(greeting: raise "greeting is required")
  # ...
end

Если вы планируете делать это много (и не можете использовать Ruby 2.1+), вы можете использовать вспомогательный метод, например:

def required
  method = caller_locations(1,1)[0].label
  raise ArgumentError,
    "A required keyword argument was not specified when calling '#{method}'"
end

def say(greeting: required)
  # ...
end

say # => A required keyword argument was not specified when calling 'say'

Ответ 2

В настоящий момент (Ruby 2.0.0-preview1) вы можете использовать следующую подпись метода:

def say(greeting: greeting_to_say)
  puts greeting
end

greeting_to_say является просто заполнителем, который не будет оцениваться, если вы предоставите аргумент именованному параметру. Если вы не передадите его (вызов только say()), рубин вызовет ошибку:

NameError: undefined local variable or method `greeting_to_say' for (your scope)

Однако эта переменная не привязана ни к чему, и насколько я могу судить, нельзя ссылаться изнутри вашего метода. Вы по-прежнему использовали бы greeting в качестве локальной переменной для ссылки на то, что было передано для именованного параметра.

Если бы вы действительно делали это, я бы рекомендовал использовать def say(greeting: greeting), чтобы сообщение об ошибке ссылалось на имя, которое вы указываете на свой параметр. Я только выбрал разные в приведенном выше примере, чтобы проиллюстрировать, какой рубин будет использоваться в сообщении об ошибке, которое вы получите, чтобы не доставлять аргумент требуемому именованному параметру.

Тангенциально, если вы вызываете say('hi'), ruby ​​поднимет ArgumentError: wrong number of arguments (1 for 0), который, я думаю, немного запутан, но это только preview1.

Ответ 3

Объединение решений из @awendt и @Adam,

def say(greeting: ->{ raise ArgumentError.new("greeting is required") }.call)
  puts greeting
end

Вы можете сушить это с помощью чего-то вроде:

def required(arg)
  raise ArgumentError.new("required #{arg}")
end

def say(greeting: required('greeting'))
  puts greeting
end

И комбинируя это с решением @Marc-Andre: https://gist.github.com/rdp/5390849

Ответ 4

Как насчет:

def say(greeting: nil)
  greeting or raise ArgumentError
  puts greeting
end

say                     # => raises ArgumentError
say(greeting: 'howdy')  # => puts 'howdy'

Кроме этого, это будет сложно. Согласно этот сайт, аргументы ключевого слова "называются параметрами, которые имеют значения по умолчанию."

Ответ 5

В Ruby 2.3 я могу сделать

def say(greeting:)
  puts greeting
end