2011-10-09 14 views
5

Sto imparando le basi di Ruby (appena iniziato) e mi sono imbattuto nello Hash.[] method. E 'stato introdotto conEsistono "regole" per lo zucchero sintattico di Ruby?

a = ["foo", 1, "bar", 2] 
=> ["foo", 1, "bar", 2] 
Hash[*a] 
=> {"foo"=>1, "bar"=>2} 

Con un piccolo pensiero, ho capito che Hash[*a] è equivalente a Hash.[](*a) o Hash.[] *a. La mia domanda è: perché è così. Cos'è che ti consente di inserire lo *a tra parentesi quadre, e c'è una sorta di regola per dove e quando può essere utilizzato "it"?

Modifica: La mia formulazione sembra causare una certa confusione. Non sto chiedendo l'espansione dell'array. Ho capito. La mia domanda è fondamentalmente la seguente: se [] è un nome di metodo, perché è corretto inserire gli argomenti tra parentesi? Sembra quasi - ma non del tutto - come dire che se hai un metodo Foo.dood e vuoi passare la stringa "hey" ad esso, allora potresti scrivere Foo.do"hey"od.

+0

Vedo molte risposte incentrate su '* a' in un'invocazione di metodo. Tuttavia, sarebbe bello vedere altre produzioni affrontate, ad esempio perché '[1, * a]' funziona "come previsto" (che produce un risultato diverso da '[1, a]') e perché '[* a, 1] 'non è valido. Sarebbe anche bello vedere come "splat" si riferisce al compito e come può/fa interagire con l'assegnazione-decomposizione di Ruby ... forse probabilmente una domanda SO diversa interamente ;-) Sarebbe * davvero bello * se ci fosse un specifica semi-formale rubino. Collegamenti a quasi-specifiche renderebbero le risposte migliori. –

+0

@pst: buone domande. Se fai una nuova domanda su SO, pubblica qui il link in modo che io possa seguirlo. –

+0

nota che il modo usuale è di inviare una serie di coppie: Hash [[[key1, value1], [key2, value2]]] – tokland

risposta

3

ci sono un paio metodi che rubino consente di chiamare in uno speciale modo. Questi sono i [] come lei ha menzionato, il +, -, == e simili come qualcun altro ha menzionato.Un altro esempio importante sono i metodi del modulo something=(value) che possono essere chiamati con object.something = value e consentono di creare accessor.

Edit:

Fun fatto 1: se si definisce un metodo + si ottiene += gratuitamente.

Fun fatto 2: se si definisce un <=> si ottiene tutti i metodi di confronto, per gentile concessione di Comparable

+0

Quindi c'è una lista da qualche parte di questa roba "speciale"? –

+1

C'è un elenco di operatori che possono essere sovrascritti [qui] (http://www.zenspider.com/Languages/Ruby/QuickRef.html#28) –

4

Hash["a", "b", "c", "d"] è equivalente a Hash.[]("a", "b", "c", "d"). Quasi tutto in Ruby è una chiamata al metodo. 5 + 5 equivale a 5.+(5).

Dato a = ["a", "b", "c", "d"]Hash[*a] è equivalente a Hash["a", "b", "c", "d"], che a sua volta è equivalente a Hash.[]("a", "b", "c", "d"). Allo stesso modo, equivale a foo("a", "b", "c", "d") Questo è chiamato l'operatore di esplosione e consente di inviare un array a un metodo e ogni elemento nell'array conta come un argomento per il metodo, invece di inviare l'array al metodo come primo argomento.


Per rispondere specificamente l'aggiornamento, non c'è niente di speciale che permette di inserire *a all'interno delle parentesi. Le parentesi sono solo zucchero per una normale chiamata di metodo. L'unica cosa "speciale" qui è che è possibile inviare *a a qualsiasi metodo.

+0

Quindi quali sono [tutti] i luoghi in cui è consentita l'espansione dello splat? (Ce n'è almeno uno in più relativo all'invocazione del metodo AFAIK.) Aggiornamento –

+0

? Non ho aggiornato nulla. Quindi stai dicendo che ovunque le parentesi quadre si presentano in Ruby come nome di un metodo, puoi usare le parentesi invece delle parentesi per contenere l'elenco degli argomenti? Qualsiasi vecchio metodo 'Foo. []' Gli argomenti a, b, e c potrebbero essere scritti come 'Foo [a, b, c]'? E 'solo una caratteristica del linguaggio magico? –

+0

Questo è corretto. Un metodo chiamato [] può essere invocato con lo zucchero 'my_obj [foo]'. Un metodo chiamato [] = può essere invocato con 'my_obj [foo] = bar'. Questo si trasforma in 'my_obj. [] = (Foo, bar)'. Questo è ciò che alimenta la sintassi delle istanze di 'Hash'. C'è anche 'Dir [" glob pattern "]', che si trasforma in 'Dir. [] (" Glob pattern ")'. –

0

Il metodo *<Array> indica a Ruby di non prendere l'array come matrice, ma di utilizzare l'array "espanso".

Esempio:

def test(*argv) 
    p argv 
end 

a = [1,2,3] 
test(a) #-> [[1, 2, 3]] 
test(*a) #-> [1, 2, 3]  

Con test(a) l'array a è l'unico parametro.

Con test(*a) a viene utilizzato come un elenco di parametri.


Nel tuo caso

a = ["foo", 1, "bar", 2] 
Hash[*a] 

è simile a

Hash[*a] sarebbe

Hash[["foo", 1, "bar", 2]] 
+0

Giusto, ma dove è permesso o no? (ad esempio, quali sono le regole di produzione?) –

+0

Dipende dal metodo in cui viene utilizzato. 'a' è un array,' * a' è un elenco di parametri. Quindi, la domanda non è, è '* a' permesso, ma: Ho bisogno di un array come parametro, o ho bisogno di un elenco di parametri. – knut

+0

La mia domanda non riguarda l'espansione dell'array. Riguarda il metodo '[]' e in particolare il motivo per cui è corretto inserire argomenti all'interno di queste parentesi. –

2

Credo che la sintassi di Ruby è definito in parse.y per YARV Ruby.

+0

+1 per contrastare l'ingiustificato downgrade di IMHO. –

Problemi correlati