Nazwane parametry w Ruby 2

Nie do końca rozumiem, jak działają nazwane parametry w Rubim 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)
Jest traktowany jak haszysz. I to jest bardzo zabawne, ponieważ aby użyć nazwanych parametrów w Rubim 2.0 i musi ustawić dla nich domyślne wartości:
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

Które bardzo podobne do zachowania, które miało wcześniej Ruby z wartościami domyślnych parametrów:

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
Wiem, dlaczego tak się dzieje i prawie jak to działa.

Ale jestem tylko ciekaw, musi używam domyślnego wartości parametrów Jeśli używam nazwanych parametrów?

Czy ktoś może mi powiedzieć, jaka jest różnica między tymi dwoma?
def test1(var1="default value123")
  #.......
end

def test1(var1:"default value123")
  #.......
end
Author: the Tin Man, 2013-03-09

8 answers

Po pierwsze, ostatni przykład, który opublikowałeś, wprowadza w błąd. Całkowicie się nie Zgadzam, że zachowanie jest podobne do poprzedniego. Ostatni przykład przekazuje parametr hash jako pierwszy opcjonalny parametr, co jest zupełnie inną rzeczą!

Jeśli nie chcesz mieć wartości domyślnej, możesz po prostu użyć nil.

Jeśli chcesz przeczytać dobry writeup, zobacz " argumenty słowa kluczowego Ruby 2 ".

 23
Author: phoet,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-06-30 18:56:38

Myślę, że odpowiedź na twoje zaktualizowane pytanie można wyjaśnić wyraźnymi przykładami. W poniższym przykładzie masz opcjonalne parametry w jawnej kolejności:

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'

Podejście nazwanych parametrów jest inne. Nadal pozwala na podanie wartości domyślnych, ale pozwala wywoływaczowi określić, który z parametrów ma być podany:

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'

Chociaż prawdą jest, że oba podejścia są podobne, gdy nie mają parametrów, różnią się, gdy użytkownik zapewnia parametry metody. Za pomocą nazwanych parametrów wywołujący może określić, który parametr jest dostarczany. W szczególności, ostatni przykład (podanie tylko adresu) nie jest do końca osiągalny w pierwszym przykładzie; można uzyskać podobne wyniki tylko poprzez podanie obu parametrów do metody. To sprawia, że podejście nazwanych parametrów jest znacznie bardziej elastyczne.

 51
Author: AndyV,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-12-09 17:41:41

Zgadzam się z Tobą, że dziwnie jest wymagać wartości domyślnych jako ceny za używanie nazwanych parametrów i widocznie opiekunowie Ruby zgadzają się z nami! Ruby 2.1 usunie wymóg wartości domyślnej z 2.1.0-preview1 .

 14
Author: Josh Diehl,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-10-11 03:09:37

Począwszy od Ruby 2.1.0, nie musisz już ustawiać domyślnych wartości dla nazwanych parametrów. Jeśli pominiesz domyślną wartość parametru, wywołujący będzie musiał ją podać.

def concatenate(val1: 'default', val2:)
  "#{val1} #{val2}"
end

concatenate(val2: 'argument')
#=> "default argument"

concatenate(val1: 'change')
#=> ArgumentError: missing keyword: val2

Podane:

def test1(var1="default value123")
  var1
end

def test2(var1:"default value123")
  var1
end

Zachowają się tak samo, gdy nie podadzą argumentu:

test1
#=> "default value123"

test2
#=> "default value123"

Ale zachowają się znacznie inaczej, gdy argument zostanie przekazany:

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"
 13
Author: trliner,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-12-09 17:40:21

To jest obecne we wszystkich innych odpowiedziach, ale chcę wyodrębnić tę esencję.

Istnieją cztery rodzaje parametrów:

             Required     Optional
Positional | def PR(a)  | def PO(a=1) |
Keyword    | def KR(a:) | def KO(a:1) |

Podczas definiowania funkcji argumenty pozycyjne są podawane przed argumentami słów kluczowych, a argumenty wymagane przed argumentami opcjonalnymi.

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: wymagany argument słowa kluczowego (bez wartości domyślnej) JEST NOWY od Ruby 2.1.0, jak wspominali inni.

 8
Author: Chris Cox,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-09-10 21:17:08
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. 

Możesz zdefiniować wartość domyślną i nazwę parametru, a następnie wywołać metodę tak, jak byś ją wywołał, gdybyś miał parametry "nazwane" oparte na haszu, ale bez potrzeby definiowania wartości domyślnych w swojej metodzie.

Potrzebowałbyś tego w swojej metodzie dla każdego "nazwanego parametru", jeśli używałeś hasha.

b = options_hash[:b] || 2

Jak w:

  def test(a = 1, options_hash)
    b = options_hash[:b] || 2
    c = options_hash[:c] || 3
    p [a,b,c]
  end
 2
Author: aaandre,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-07-12 18:35:39

Zgodnie z "Ruby 2.0.0 by Example " musisz mieć domyślne wartości:

W Rubim 2.0.0, argumenty słów kluczowych muszą mieć domyślne wartości lub muszą być przechwycone przez **extra na końcu.

 2
Author: Michael Fürstenberg,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-12-09 17:42:47

Możesz zdefiniować nazwane parametry jak

def test(var1: var1, var2: var2, var3: var3)
  puts "#{var1} #{var2} #{var3}"
end

Jeśli nie podasz jednego z parametrów, to Ruby będzie narzekać na undefined local variable or method.

 0
Author: Clemens Helm,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-07-08 08:53:55