Cosa fa un operatore double * (splat)


214

Hai visto una funzione dichiarata come questa?

def foo a, **b
  ...
end

Capisco che un singolo *è l'operatore splat. Cosa **significa?

Risposte:


373

Ruby 2.0 ha introdotto argomenti per parole chiave e si **comporta come *, ma per argomenti per parole chiave. Restituisce un hash con coppie chiave / valore.

Per questo codice:

def foo(a, *b, **c)
  [a, b, c]
end

Ecco una demo:

> foo 10
=> [10, [], {}]
> foo 10, 20, 30
=> [10, [20, 30], {}]
> foo 10, 20, 30, d: 40, e: 50
=> [10, [20, 30], {:d=>40, :e=>50}]
> foo 10, d: 40, e: 50
=> [10, [], {:d=>40, :e=>50}]

44
Questo risponde perfettamente alla domanda, ma ho avuto un piccolo addendum. Proprio come è possibile utilizzare l'operatore splat sull'array che si passa, il doppio splat può essere utilizzato sugli hash. Se opts = {d: 40, e: 50}, allora foo 10, opts, f: 60assegnerà {f: 60}a c, mentre foo 10, **opts, f: 60assegnerà {d: 40, e: 50, f: 60}. Per ottenere il secondo effetto, in precedenza si avrebbero mergeesplicitamente le matrici.
brymck,

Suppongo che questo sia utile per impostare parametri hash opzionali per un metodo
bigpotato il

Probabilmente vale la pena notare che se si mescolano argomenti-parola chiave con parola chiave splat, la parola chiave splat deve venire dopo gli argomenti della parola chiave.
MrMesees,

43

Questo è l' operatore double splat che è disponibile da Ruby 2.0.

Cattura tutti gli argomenti di parole chiave (che può anche essere un semplice hash, che era il modo idiomatico di emulare argomenti di parole chiave prima che diventassero parte del linguaggio Ruby)

def my_method(**options)
  puts options.inspect
end

my_method(key: "value")

Il codice sopra viene stampato {key:value}sulla console.

Proprio come il singolo operatore splat cattura tutti gli argomenti regolari, ma invece di un array ottieni un hash .

Esempio di vita reale:

Ad esempio in Rails il cyclemetodo è simile al seguente:

def cycle(first_value, *values)
  options = values.extract_options!
  # ...
end

Questo metodo può essere chiamato in questo modo: cycle("red", "green", "blue", name: "colors").

Questo è un modello abbastanza comune: accetti un elenco di argomenti e l'ultimo è un hash delle opzioni, che può essere estratto - ad esempio - usando ActiveSupport extract_options!.

In Ruby 2.0 puoi semplificare questi metodi:

def cycle(first_value, *values, **options)
  # Same code as above without further changes!
end

È vero che è solo un piccolo miglioramento se si sta già utilizzando ActiveSupport ma per il semplice Ruby il codice guadagna molta concisione.


20

Inoltre, puoi usarlo nel lato chiamante in questo modo:

def foo(opts); p opts end
bar = {a:1, b:2}

foo(bar, c: 3)
=> ArgumentError: wrong number of arguments (given 2, expected 1)

foo(**bar, c: 3)
=> {:a=>1, :b=>2, :c=>3}

5
Wow, double-splat è analogo all'operatore di diffusione oggetti di ES6.
mpoisot,

1
Grazie, questa è la conferma che stavo cercando.
Qortex,
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.