Was macht ein Double * (Splat) -Operator?

214

Haben Sie eine so deklarierte Funktion gesehen?

def foo a, **b
  ...
end

Ich verstehe, dass eine Single *der Splat-Operator ist. Was heißt **das

Roy Lee
quelle

Antworten:

373

Ruby 2.0 führte Schlüsselwortargumente ein und **verhält sich wie *, jedoch für Schlüsselwortargumente. Es gibt einen Hash mit Schlüssel / Wert-Paaren zurück.

Für diesen Code:

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

Hier ist eine 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
quelle
44
Dies beantwortet die Frage perfekt, aber ich hatte einen kleinen Nachtrag. So wie der Splat-Operator für das übergebene Array verwendet werden kann, kann der Double-Splat für Hashes verwendet werden. Wenn opts = {d: 40, e: 50}, dann foo 10, opts, f: 60wird zuweisen {f: 60}zu c, während foo 10, **opts, f: 60zuweist {d: 40, e: 50, f: 60}. Um den zweiten Effekt zu erzielen, hätten Sie zuvor mergedie Arrays explizit d.
Brymck
Ich würde annehmen, dass dies nützlich ist, um optionale Hash-Parameter für eine Methode
festzulegen
Wahrscheinlich ist es eine Anmerkung wert, dass beim Mischen von Keyword-Argumenten mit Keyword-Splat das Keyword-Splat nach den Keyword-Argumenten stehen muss.
MrMesees
43

Dies ist der Double-Splat- Operator, der seit Ruby 2.0 verfügbar ist.

Es erfasst alle Schlüsselwortargumente (was auch ein einfacher Hash sein kann, was die idiomatische Methode war, Schlüsselwortargumente zu emulieren, bevor sie Teil der Ruby-Sprache wurden).

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

my_method(key: "value")

Der obige Code wird {key:value}auf der Konsole gedruckt .

Genau wie der einzelne Splat-Operator alle regulären Argumente erfasst, erhalten Sie jedoch anstelle eines Arrays einen Hash .

Beispiel aus der Praxis:

In Rails cyclesieht die Methode beispielsweise folgendermaßen aus:

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

Diese Methode kann folgendermaßen aufgerufen werden : cycle("red", "green", "blue", name: "colors").

Dies ist ein weit verbreitetes Muster: Sie akzeptieren eine Liste von Argumenten und das letzte ist ein Options-Hash, der beispielsweise mit ActiveSupport extrahiert werden kann extract_options!.

In Ruby 2.0 können Sie diese Methoden vereinfachen:

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

Zugegeben, es ist nur eine geringfügige Verbesserung, wenn Sie ActiveSupport bereits verwenden, aber für einfaches Ruby gewinnt der Code ziemlich viel Prägnanz.

Daniel Rikowski
quelle
20

Darüber hinaus können Sie es auf der Anruferseite wie folgt verwenden:

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
quelle
5
Wow, Double-Splat ist analog zum Objekt-Spread-Operator von ES6.
Mpoisot
1
Danke, das ist die Bestätigung, nach der ich gesucht habe.
Qortex