Co robi operator double * (splat)

214

Czy widziałeś taką funkcję zadeklarowaną?

def foo a, **b
  ...
end

Rozumiem, że jeden *jest operatorem splat. Co **znaczy

Roy Lee
źródło

Odpowiedzi:

373

Ruby 2.0 wprowadził argumenty słów kluczowych i **działa jak *, ale dla argumentów słów kluczowych. Zwraca skrót z parami klucz / wartość.

Dla tego kodu:

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

Oto 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}]
Dogbert
źródło
44
To doskonale odpowiada na pytanie, ale miałem niewielki aneks. Tak jak operator splat może być używany na mijanej tablicy, podwójna ikona może być używana w haszach. Jeśli opts = {d: 40, e: 50}, to foo 10, opts, f: 60przypisze {f: 60}do c, a foo 10, **opts, f: 60przypisze {d: 40, e: 50, f: 60}. Aby osiągnąć drugi efekt, wcześniej mergetablice byłyby jawnie jawne.
brymck
Zakładam, że jest to przydatne do ustawiania opcjonalnych parametrów skrótu dla metody
bigpotato
Prawdopodobnie warto zauważyć, że w przypadku mieszania argumentów słowa kluczowego ze słowem kluczowym splat słowo kluczowe musi następować po argumentach słowa kluczowego.
MrMesees
43

To jest operator podwójnej ikony , który jest dostępny od Ruby 2.0.

Przechwytuje wszystkie argumenty słów kluczowych (które mogą być również prostymi skrótami, co było idiomatycznym sposobem emulacji argumentów słów kluczowych, zanim stały się częścią języka Ruby)

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

my_method(key: "value")

Powyższy kod jest drukowany {key:value}na konsoli.

Podobnie jak operator pojedynczej ikony przechwytuje wszystkie zwykłe argumenty, ale zamiast tablicy otrzymujesz skrót .

Przykład z życia:

Na przykład w Railsach cyclemetoda wygląda następująco:

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

Metoda ta może być wywołana tak: cycle("red", "green", "blue", name: "colors").

Jest to dość powszechny wzorzec: akceptujesz listę argumentów, a ostatni to skrót opcji, który można wyodrębnić - na przykład - za pomocą ActiveSupport extract_options!.

W Ruby 2.0 możesz uprościć te metody:

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

Wprawdzie jest to tylko niewielka poprawa, jeśli już używasz ActiveSupport, ale dla zwykłego Ruby kod zyskuje dość zwięzłość.

Daniel Rikowski
źródło
20

Ponadto można go używać po stronie dzwoniącego w następujący sposób:

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}
kuboon
źródło
5
Wow, podwójna ikona jest podobna do operatora rozprzestrzeniania obiektów ES6.
mpoisot
1
Dzięki, to potwierdzenie, którego szukałem.
Qortex,