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

Именованные параметры в 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
4b9b3361

Ответ 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.