2013-03-09 19 views
30

Non capisco completamente come funzionano i parametri denominati in Ruby 2.0.Parametri nominati in Ruby 2

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) 

è trattato come un hash. Ed è molto divertente perché per utilizzare parametri denominati in Ruby 2.0 I must impostati i valori di default per loro:

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 

che molto simile al comportamento che Rubino aveva prima con parametri preimpostati:

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 

So perché succede e quasi come funziona.

Ma sono solo curioso, deve Uso i valori predefiniti per i parametri se utilizzo i parametri denominati?

E qualcuno può dirmi qual è la differenza tra questi due?

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

def test1(var1:"default value123") 
    #....... 
end 
+3

Il primo ha un parametro opzionale. L'ultimo ha chiamato parametri. Quindi puoi omettere il parametro per entrambi, ma se vuoi passare un parametro, l'ultimo deve essere nominato. –

+0

possibile duplicato di [Nessun parametro con nome in Ruby?] (Http://stackoverflow.com/questions/9612499/no-named-parameters-in-ruby) –

+0

il primo esempio non utilizza i parametri denominati – baash05

risposta

12

In primo luogo, l'ultimo esempio pubblicato è fuorviante. Non sono assolutamente d'accordo sul fatto che il comportamento sia simile a quello precedente. L'ultimo esempio passa l'hash dell'argomento come primo parametro facoltativo che è una cosa diversa!

Se non si desidera avere un valore predefinito, è sufficiente utilizzare nil.

Se si desidera leggere una buona scrittura, vedere "Ruby 2 Keyword Arguments".

+2

Un altro buon sommario è http://blog.marc-andre.ca/2013/02/23/ruby-2 -by-example/ –

+0

+1 al [link brainspec] (http://brainspec.com/blog/2012/10/08/keyword-arguments-ruby-2-0/). È una descrizione di prima lettura di facile comprensione. –

1

Secondo "Ruby 2.0.0 by Example" è necessario disporre di default:

In Ruby 2.0.0, keyword arguments must have defaults, or else must be captured by **extra at the end.

+0

Dai un'occhiata anche a https://speakerdeck.com/peterc/ruby-2-dot-0-walkthrough-the-best-bits per una buona panoramica. –

+0

è diverso dagli argomenti predefiniti in C# o Java. –

0

È possibile define denominati parametri come

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

Se non si passa uno dei parametri, allora Rubino si lamenterà un undefined local variable or method.

2
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. 

È possibile definire il valore di default e il nome del parametro e quindi chiamare il metodo il modo in cui si sarebbe chiamata che se si fosse basata su hash "chiamato" i parametri, ma senza la necessità di definire le impostazioni predefinite nel metodo .

È necessario questo nel metodo per ogni "parametro denominato" se si utilizzava un hash.

b = options_hash[:b] || 2 

come in:

def test(a = 1, options_hash) 
    b = options_hash[:b] || 2 
    c = options_hash[:c] || 3 
    p [a,b,c] 
    end 
21

Penso che la risposta alla tua domanda aggiornato può essere spiegata con esempi espliciti. Nell'esempio riportato di seguito sono disponibili parametri facoltativi in ​​un ordine esplicito:

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' 

L'approccio al parametro denominato è diverso.Esso permette ancora di fornire valori predefiniti ma consente al chiamante di determinare quali, se del caso, dei parametri per fornire:

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' 

Mentre è vero che i due approcci sono simili quando fornito senza parametri, si differenziano quando l'utente fornisce parametri per il metodo. Con i parametri denominati, il chiamante può specificare quale parametro viene fornito. Nello specifico, l'ultimo esempio (che fornisce solo l'indirizzo) non è del tutto raggiungibile nel primo esempio; è possibile ottenere risultati simili SOLO fornendo i parametri BOTH al metodo. Questo rende i parametri nominati molto più flessibili.

12

Sono d'accordo con te che è strano richiedere valori predefiniti come prezzo per l'utilizzo di parametri con nome, ed evidentemente i manutentori di Ruby sono d'accordo con noi! Ruby 2.1 sarà drop the default value requirement as of 2.1.0-preview1.

+7

Indovina cosa fa schifo! Se hai definito una funzione che accetta un argomento di parole chiave e poi qualcuno la chiama con un argomento semplice ... ottieni 'ArgumentError: numero errato di argomenti (1 per 0)' piuttosto che, o dici 'ArgumentError: parola chiave mancante per parola chiave argomento (argomento 1 di 1) '. – Ziggy

+0

Penso che uno schema comune sia quello di usare gli argomenti con nome quando l'elenco degli argomenti è troppo lungo o ha troppi optionals.In questi casi, probabilmente si desidera impedire alle persone di passare un valore come argomento e presupponendo che conoscano l'ordine corretto. –

+0

Io li uso per evitare questo anti-pattern: 'def f (arg1, arg2, flag = true)' Io invece faccio 'def f (arg1, arg2, flag: true)' in modo che la persona che chiama la funzione DEVE conoscere il natura della bandiera. – Ziggy

8

A partire da Ruby 2.1.0, non è più necessario impostare valori predefiniti per i parametri denominati. Se si omette il valore predefinito per un parametro, al chiamante verrà richiesto di fornirlo.

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

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

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

Dato:

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

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

si comporteranno allo stesso modo quando non passò un argomento:

test1 
#=> "default value123" 

test2 
#=> "default value123" 

Ma si comporteranno in modo molto diverso quando un argomento è superato:

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" 
3

Questo è presente in tutte le altre risposte, ma voglio estrarre questa essenza.

ci sono quattro tipi di parametri:

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

Quando si definisce una funzione, argomenti posizionali vengono configurate prima di argomenti a parola chiave, e richiedono argomenti prima di quelli opzionali.

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] 

modifica: l'argomento della parola chiave richiesto (senza un valore predefinito) è nuovo a partire da Ruby 2.1.0, come menzionato da altri.

Problemi correlati