Именованные параметры в Ruby 2
Я не понимаю, как работают именованные параметры в Ruby 2.0.
def test(var1, var2, var3)
puts "#{var1} #{var2} #{var3}"
end
test(var3:"var3-new", var1: 1111, var2: 2222) #wrong number of arguments (1 for 3) (ArgumentError)
он рассматривался как хэш. И это очень забавно, потому что для использования именованных параметров в Ruby 2.0 я должен устанавливать для них значения по умолчанию:
def test(var1: "var1", var2: "var2", var3: "var3")
puts "#{var1} #{var2} #{var3}"
end
test(var3:"var3-new", var1: 1111, var2: 2222) # ok => 1111 2222 var3-new
который очень похож на поведение, которое ранее имел Ruby с значениями параметров по умолчанию:
def test(var1="var1", var2="var2", var3="var3")
puts "#{var1} #{var2} #{var3}"
end
test(var3:"var3-new", var1: 1111, var2: 2222) # ok but ... {:var3=>"var3-new", :var1=>1111, :var2=>2222} var2 var3
Я знаю, почему это происходит и почти как это работает.
Но мне просто интересно: must Я использую значения по умолчанию для параметров, если я использую именованные параметры?
И, может ли кто-нибудь сказать мне, какая разница между этими двумя тогда?
def test1(var1="default value123")
#.......
end
def test1(var1:"default value123")
#.......
end
Ответы
Ответ 1
Во-первых, последний приведенный вами пример вводит в заблуждение. Я полностью не согласен с тем, что поведение похоже на предыдущее. Последний пример передает аргумент хэш в качестве первого необязательного параметра, который является другой вещью!
Если вы не хотите иметь значение по умолчанию, вы можете просто использовать nil
.
Если вы хотите прочитать хорошую запись, см. "" Аргументы ключевого слова Ruby 2".
Ответ 2
Я думаю, что ответ на ваш обновленный вопрос можно объяснить явными примерами. В приведенном ниже примере у вас есть необязательные параметры в явном порядке:
def show_name_and_address(name="Someone", address="Somewhere")
puts "#{name}, #{address}"
end
show_name_and_address
#=> 'Someone, Somewhere'
show_name_and_address('Andy')
#=> 'Andy, Somewhere'
Именованный подход к параметрам отличается. Он по-прежнему позволяет вам предоставлять значения по умолчанию, но позволяет вызывающему определить, какие параметры предоставить:
def show_name_and_address(name: "Someone", address: "Somewhere")
puts "#{name}, #{address}"
end
show_name_and_address
#=> 'Someone, Somewhere'
show_name_and_address(name: 'Andy')
#=> 'Andy, Somewhere'
show_name_and_address(address: 'USA')
#=> 'Someone, USA'
Хотя верно, что оба подхода одинаковы при отсутствии параметров, они различаются, когда пользователь предоставляет параметры методу. С именованными параметрами вызывающий может указать, какой параметр предоставляется. В частности, последний пример (содержащий только адрес) не совсем достижим в первом примере; вы можете получить аналогичные результаты ТОЛЬКО, предоставив BOTH параметрам методу. Это значительно упрощает именованные параметры.
Ответ 3
Я согласен с вами в том, что странно требовать значения по умолчанию в качестве цены за использование именованных параметров, и, очевидно, соглашатели Ruby согласны с нами! Ruby 2.1 будет отказаться от значения по умолчанию по 2.1.0-preview1.
Ответ 4
По Ruby 2.1.0 вам больше не нужно устанавливать значения по умолчанию для именованных параметров. Если вы опустите значение по умолчанию для параметра, вызывающий должен будет его предоставить.
def concatenate(val1: 'default', val2:)
"#{val1} #{val2}"
end
concatenate(val2: 'argument')
#=> "default argument"
concatenate(val1: 'change')
#=> ArgumentError: missing keyword: val2
Дано:
def test1(var1="default value123")
var1
end
def test2(var1:"default value123")
var1
end
Они будут вести себя одинаково, если не передали аргумент:
test1
#=> "default value123"
test2
#=> "default value123"
Но они будут вести себя по-разному, когда передается аргумент:
test1("something else")
#=> "something else"
test2("something else")
#=> ArgumentError: wrong number of arguments (1 for 0)
test1(var1: "something else")
#=> {:var1=>"something else"}
test2(var1: "something else")
#=> "something else"
Ответ 5
Это присутствует во всех других ответах, но я хочу извлечь эту сущность.
Существует четыре вида параметров:
Required Optional
Positional | def PR(a) | def PO(a=1) |
Keyword | def KR(a:) | def KO(a:1) |
При определении функции перед аргументами аргументов указываются позиционные аргументы и требуемые аргументы перед необязательными.
irb(main):006:0> def argtest(a,b=2,c:,d:4)
irb(main):007:1> p [a,b,c,d]
irb(main):008:1> end
=> :argtest
irb(main):009:0> argtest(1,c: 3)
=> [1, 2, 3, 4]
irb(main):010:0> argtest(1,20,c: 3,d: 40)
=> [1, 20, 3, 40]
edit: аргумент требуемого ключевого слова (без значения по умолчанию) является новым с Ruby 2.1.0, как упоминалось другими.
Ответ 6
def test(a = 1, b: 2, c: 3)
p [a,b,c]
end
test #=> [1,2,3]
test 10 #=> [10,2,3]
test c:30 #=> [1,2,30] <- this is where named parameters become handy.
Вы можете определить значение по умолчанию и имя параметра, а затем вызвать метод так, как вы его назовёте, если бы у вас были хеш-основанные "именованные" параметры, но без необходимости определять значения по умолчанию в вашем методе.
Вам понадобится это в вашем методе для каждого "именованного параметра", если вы используете хэш.
b = options_hash[:b] || 2
как в:
def test(a = 1, options_hash)
b = options_hash[:b] || 2
c = options_hash[:c] || 3
p [a,b,c]
end
Ответ 7
В соответствии с " Ruby 2.0.0 by Example" у вас должны быть значения по умолчанию:
В Ruby 2.0.0 аргументы ключевого слова должны иметь значения по умолчанию, иначе они должны быть записаны ** в конце.
Ответ 8
Вы можете определить именованные параметры, такие как
def test(var1: var1, var2: var2, var3: var3)
puts "#{var1} #{var2} #{var3}"
end
Если вы не пройдете один из параметров, Ruby будет жаловаться на undefined local variable or method
.