2012-09-01 22 views
24

Wie man ein Tupelargument am besten weitergibt?Wie man ein Tupelargument am besten weitergibt?

Beispiel:

def foo(...): (Int, Int) = ... 

def bar(a: Int, b: Int) = ... 

Nun möchte Ich mag die Ausgabe von foo-bar passieren. Dies kann erreicht werden durch:

val fooResult = foo(...) 
bar(fooResult._1, fooResult._2) 

Dieser Ansatz sieht ein bisschen hässlich, vor allem, wenn wir mit einem n tupel mit n > 2 beschäftigen. Außerdem müssen wir das Ergebnis von foo in einem extra Wert speichern, da sonst foo mit bar(foo._1, foo._2) mehr als einmal ausgeführt werden muss.

Gibt es eine bessere Möglichkeit, das Tupel als Argument zu übergeben?

+1

mögliche Duplikate von [Wie man eine Funktion auf ein Tupel anwendet?] (Http://stackoverflow.com/questions/1987820/how-to-apply-a-function-to-a-tuple) –

Antwort

39

Es gibt eine spezielle tupled Methode zur Verfügung, für jede Funktion:

val bar2 = (bar _).tupled // or Function.tupled(bar _) 

bar2 nimmt ein Tupel von (Int, Int) (den gleichen wie bar Argumenten). Jetzt können Sie sagen:

bar2(foo()) 

Wenn Ihre Methoden waren tatsächlich funktioniert (man beachte das val Schlüsselwort) die Syntax ist viel angenehmer:

val bar = (a: Int, b: Int) => //... 
bar.tupled(foo()) 

Siehe auch

+0

Vielen Dank, das ist, was ich gesucht habe. Das wird den Trick für mich tun. Zusatzfrage: Sie haben erwähnt, dass es einen Unterschied zwischen einer Methode und einer Funktion gibt - worin besteht der Unterschied? Ich würde gerne mehr darüber wissen. Können Sie mir Referenzen/Links geben, wo ich mehr darüber lesen kann? –

+3

@JohnThreepwood: Methoden in Scala übersetzen Methoden in Java. Funktionen in Scala übersetzen in Objekte. In Scala ist dies meist transparent (Suche nach "* eta-expansion *"), aber manchmal ist die Syntax etwas anders. [Dieser Artikel] (http://jim-mcbeath.blogspot.no/2009/05/scala-functions-vs-methods.html) ist sehr umfangreich. –

+0

Großartig, vielen Dank. –

8

Verwendung tupled, als @ Tomasz erwähnt, ist ein guter Ansatz.

Sie können auch die Tupel aus foo bei der Zuordnung zurück extrahieren:

val (x, y) = foo(5) 
bar(x, y) 

Dies den Vorteil der saubereren Code hat (kein _1 und _2) und können Sie beschreibende Namen für x und y zuweisen, so dass Ihr Code leichter zu lesen.

+0

Danke. Ich stimme zu, das ist lesbarer. Ich werde diesen Trick im Hinterkopf behalten. Aber der zusätzliche Wert nervt mich ein bisschen. Ich möchte es weitergeben, ohne das Ergebnis auf einen zusätzlichen Wert zu speichern. Aber trotzdem vielen Dank für diesen Hinweis! –

5

Es lohnt sich, auch über

foo(...) match { case (a,b) => bar(a,b) } 

als Alternative zu wissen, dass Sie nicht explizit erforderlich, um ein temporäres fooResult zu erstellen. Es ist ein guter Kompromiss, wenn Geschwindigkeit und Unordnung wichtig sind. Sie können eine Funktion mit bar _ erstellen und sie dann konvertieren, um ein einzelnes Tupelargument mit .tupled zu nehmen, aber dies erzeugt jedes Mal, wenn Sie das Paar aufrufen, zwei neue Funktionsobjekte; Sie könnten das Ergebnis speichern, aber das könnte Ihren Code unnötigerweise überladen.

Für den täglichen Gebrauch (das heißt dies nicht der leistungsbegrenzenden Teil des Codes), können Sie nur

(bar _).tupled(foo(...)) 

in der Schlange.Sicher, Sie erstellen zwei zusätzliche Funktionsobjekte, aber Sie haben höchstwahrscheinlich nur das Tupel erstellt, so dass es Ihnen egal ist dass viel, oder?

+0

Vielen Dank, dass Sie auf diese Alternative hingewiesen haben. Aber warum ist ein Tupel als Rückgabewert ein Zeichen dafür, sich nicht um die Performance zu kümmern? Aber ja, du hast Recht, in meinem Programm ist die Leistung nicht so wichtig. –

+0

@JohnThreepwood - Sie müssen ein Objekt erstellen, um ein Tupel zurückzugeben. Wenn das, was Sie tun, im Vergleich zur Objekt-Erstellung teuer ist, dann ist es wahrscheinlich auch teuer im Vergleich zu zwei Objekt-Kreationen (was Sie mit "bar _" und ".tupled" erhalten). Wenn das, was Sie tun, im Vergleich zur Objekterstellung billig ist, warum haben Sie ein Objekt erstellt? Sie sollten ein Objekt mit vars übergeben haben, das Sie festlegen können. (Der letztere Ansatz ist etwas, was Sie selten tun sollten, wenn überhaupt - die Erstellung von Objekten ist ziemlich billig.) –

+0

Vielen Dank für die Klärung. Die Erklärung macht Sinn, ich werde es mir merken. –

Verwandte Themen