Gibt zwei und mehr Werte von einer Methode zurück

105

Gibt es eine Möglichkeit, mehrere Werte von der Methode zurückzugeben? Etwas wie das:

def someMethod()
  return ["a", 10, SomeObject.new]
end

[a, b, c] = someMethod
Demas
quelle

Antworten:

160
def sumdiff(x, y)
  return x+y, x-y
end
#=> nil

sumdiff(3, 4)
#=> [7, -1]

a = sumdiff(3,4)
#=> [7, -1]
a
#=> [7, -1]

a,b=sumdiff(3,4)
#=> [7, -1]
a
#=> 7
b
#=> -1

a,b,c=sumdiff(3,4)
#=> [7, -1]
a
#=> 7
b
#=> -1
c
#=> nil
Aditya Mukherji
quelle
Sie sollten die Codeformatierung verwenden, nicht die Textformatierung. Einrückungslinien vier Leerzeichen und die durch die >>Aufforderung von irb verursachte Verrücktheit verschwindet .
Chris Lutz
4
Da eine explizite Rückgabe als nicht idiomatischer Ruby betrachtet wird, können Sie auch eine implizite Rückgabe verwenden, indem Sie die Rückgabewerte explizit in eine Liste def foo_and_bar; ['foo', 'bar']; end
Dennis
43

Ruby hat eine begrenzte Form der Destrukturierungsbindung:

ary = [1, 2, 3, 4]
a, b, c = ary
p a # => 1
p b # => 2
p c # => 3

a, b, *c = ary
p c # => [3, 4]

a, b, c, d, e = ary
p d # => 4
p e # => nil

Es hat auch eine begrenzte Form der Strukturierung binden:

 a = 1, 2, 3
 p a # => [1, 2, 3]

Sie können diese beiden Formen folgendermaßen kombinieren:

a, b = b, a # Nice way to swap two variables

a, b = 1, 2, 3
p b # => 2

def foo; return 1, 2 end
a, b = foo
p a # => 1
p b # => 2

Es gibt verschiedene andere Dinge, die Sie mit der Destrukturierung / Strukturierung von Bindungen tun können. Ich habe nicht mit dem splat-Operator ( *) auf der rechten Seite gezeigt. Ich habe keine Verschachtelung gezeigt (mit Klammern). Ich habe nicht gezeigt, dass Sie Destructuring Bind in der Parameterliste eines Blocks oder einer Methode verwenden können.

Hier ist nur eine Vorspeise:

def foo(((a, b, c, d), e, *f), g, *h)
  local_variables.sort.each do |lvar| puts "#{lvar} => #{eval(lvar).inspect}" end
end

foo([[1, 2, 3], 4, 5, 6], 7, 8, 9)
# a => 1
# b => 2
# c => 3
# d => nil
# e => 4
# f => [5, 6]
# g => 7
# h => [8, 9]
Jörg W Mittag
quelle
16

Obwohl die Rückgabe mehrerer Werte oft nützlich ist, finde ich sie normalerweise als Zeiger auf eine neue Objektanforderung.

Das heißt, ich finde normalerweise, dass diese Rückgabewerte in Bedeutung / Kontext eng miteinander verbunden sind und als solche weitergegeben werden. In diesen Fällen würde ich also ein neues Objekt erstellen, um diese zusammenzubinden. Es ist ein bestimmter Code-Geruch, den ich zu erkennen gelernt habe.

Brian Agnew
quelle
4
mehr Freiheit, mehr Verantwortung. Erfahrene Rubinisten würden es ausnutzen und einige schöne Codes schreiben. während Ruby Rookies die Sache noch schlimmer machen können.
Fengd
1
Nun klar, das ist nicht immer der Fall, sonst chunkwürden solche Dinge nicht existieren. Ausgezeichnetes Prinzip. Code riecht tatsächlich. Mach weiter.
Darth Egregious
6

Sie können dies erreichen, indem Sie auch ein Array zurückgeben, wie z

def sumdiff(x, y)
    [x+y, x-y]
end

das scheint funktional äquivalent zu

def sumdiff(x, y)
    return x+y, x-y
end
Zack Xu
quelle