Übergeben eines Hashs an eine Funktion (* args) und ihre Bedeutung

72

Bei Verwendung einer Redewendung wie:

def func(*args)
  # some code
end

Was bedeutet das *args? Diese spezielle Frage zu googeln war ziemlich schwierig und ich konnte nichts finden.

Es scheint, dass alle Argumente tatsächlich vorkommen, args[0]also schreibe ich Verteidigungscode wie:

my_var = args[0].delete(:var_name) if args[0]

Aber ich bin mir sicher, dass es einen besseren Weg gibt, den ich verpasse.

shmichael
quelle

Antworten:

104

Das *ist die Splat (oder Sternchen) Operator. Im Kontext einer Methode wird eine Argumentliste mit variabler Länge angegeben. In Ihrem Fall werden alle an übergebenen Argumente funcin ein aufgerufenes Array eingefügt args. Sie können auch bestimmte Argumente vor einem Argument variabler Länge wie folgt angeben:

def func2(arg1, arg2, *other_args)
  # ...
end

Nehmen wir an, wir nennen diese Methode:

func2(1, 2, 3, 4, 5)

Wenn Sie überprüfen arg1, arg2und other_argsinnerhalb func2jetzt, werden Sie die folgenden Ergebnisse erhalten:

def func2(arg1, arg2, *other_args)
  p arg1.inspect       # => 1
  p arg2.inspect       # => 2
  p other_args.inspect # => [3, 4, 5]
end

In Ihrem Fall scheinen Sie einen Hash als Argument an Ihren zu übergeben func. In diesem Fall args[0]enthält er den Hash, wie Sie beobachten.

Ressourcen:


Update basierend auf den Kommentaren von OP

Wenn Sie einen Hash als Argument übergeben möchten, sollten Sie den Splat-Operator nicht verwenden. Mit Ruby können Sie in Ihren Methodenaufrufen Klammern weglassen, einschließlich solcher, die einen Hash angeben (mit einer Einschränkung, lesen Sie weiter). Deshalb:

my_func arg1, arg2, :html_arg => value, :html_arg2 => value2

ist äquivalent zu

my_func(arg1, arg2, {:html_arg => value, :html_arg2 => value2})

Wenn Ruby den =>Operator in Ihrer Argumentliste sieht , kann er das Argument auch ohne die explizite {...}Notation als Hash verwenden (beachten Sie, dass dies nur gilt, wenn das Hash-Argument das letzte ist!).

Wenn Sie diesen Hash sammeln möchten, müssen Sie nichts Besonderes tun (obwohl Sie wahrscheinlich einen leeren Hash als Standardwert in Ihrer Methodendefinition angeben möchten):

def my_func(arg1, arg2, html_args = {})
  # ...
end
Daniel Vandersluis
quelle
Also muss ich if args[0]beim Zugriff auf die Parameter die Abwehrtechnik anwenden?
Shmichael
@shmichael Wie rufst du deine Methode auf? Wenn Sie nicht möchten, dass Ihre Argumente in ein Array wie dieses eingefügt werden, verwenden Sie den Splat nicht.
Daniel Vandersluis
Ich verwende die Rails-Konvention (z my_func arg1, arg2, :html_arg => value, :html_arg2 => value2. B. ). Idealerweise möchte ich einen args Hash erhalten und kein args Array, das einen Hash enthalten könnte .
Shmichael