Cosa significa la sintassi [*a..b] in Ruby?
Domanda
NOTA: Mischa's Splat su github Ha molti esempi interattivi fantastici di * in azione.
In Google, ho scoperto che un modo per iterare su una serie di numeri in Ruby (il tuo classico stile C per loop)
for (i = first; i <= last; i++) {
whatever(i);
}
è fare qualcosa del genere
[*first..last].each do |i|
whatever i
end
Ma cosa sta succedendo esattamente con quello [*first..last]
sintassi? Ho giocato in giro con irb
E vedo questo:
ruby-1.9.2-p180 :001 > 0..5
=> 0..5
ruby-1.9.2-p180 :002 > [0..5]
=> [0..5]
ruby-1.9.2-p180 :003 > [*0..5]
=> [0, 1, 2, 3, 4, 5]
ruby-1.9.2-p180 :004 > *0..5
SyntaxError: (irb):4: syntax error, unexpected tDOT2, expecting tCOLON2 or '[' or '.'
*0..5
^
Tutto ciò che ho letto online discute l'asterisco unario come utile per l'espansione e il collasso degli argomenti passati a un metodo, utile per elenchi di argomenti di lunghezza variabile
def foo(*bar)
bar
end
foo 'tater' # => ["tater"]
foo 'tater', 'tot' # => ["tater", "tot"]
E lo capisco, ma non vedo come si applica all'espansione fatta nel mio blocco sopra.
Per essere chiari, so che il Ruby Way è di iterare su un array o una raccolta, non usare la lunghezza dell'array e iterare con un indice intero. Tuttavia, in questo esempio, ho davvero a che fare con un elenco di numeri interi. :)
Soluzione
[*1..10]
è la stessa cosa di
(1..10).to_a # call the "to array" method
Istanze del Array
classe hai creato implement Enumerable
Quindi il tuo loop funziona. Su classi che definiscono a to_a
metodo, puoi usare il operatore splat sintassi con parentesi. Splat fa molto di più che chiamare #to_a
Tuttavia, varrebbe una ricerca su Google da solo.
Ora, nel tuo caso, il Range
La classe stessa è già un Enumerable
Quindi potresti solo fare:
(first..last).each do |v|
...
end
Altri suggerimenti
[first..last]
è un array contenente solo 1 oggetto di portata. [*first..last]
è un array contenente gli elementi di quell'intervallo che sono stati inviati come elenco di argomenti. *
funziona nel contesto di un elenco di argomenti.
Si chiama operatore splat. Se lo usi all'interno di determinate posizioni come una posizione di argomento o un array, si espanderà nei suoi elementi:
a = [1]
[*a, 3] # => [1, 3]
b = [1, 2]
[*b, 3] # => [1, 2, 3]
Non puoi usarlo nudo o in gamme:
*a..3 # => error.
(*a..3) # => error.
Quando hai qualcosa che non è un array, torna da solo:
a = 1
[*a, 3] # => [1, 3]