2012-09-01 14 views
24

¿Cómo pasar un argumento de tupla de la mejor manera?¿Cómo pasar un argumento de tupla de la mejor manera?

Ejemplo:

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

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

Ahora me gustaría para pasar la salida de foo-bar. Esto puede lograrse con:

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

Este enfoque parece un poco feo, especialmente cuando tratamos con una tupla n con n > 2. También tenemos que almacenar el resultado de foo en un valor adicional, porque de lo contrario foo tiene que ser ejecutado más de una vez usando bar(foo._1, foo._2).

¿Hay una mejor manera de pasar por la tupla como argumento?

+1

posible duplicado de [Cómo aplicar una función a una tupla?] (Http://stackoverflow.com/questions/1987820/how-to-apply-a-function-to-a-tuple) –

Respuesta

39

No es un método especial tupled disponibles para cada función:

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

bar2 toma una tupla de (Int, Int) (igual que bar argumentos). Ahora se puede decir:

bar2(foo()) 

Si sus métodos eran en realidad funciones (nótese la palabra clave val) la sintaxis es mucho más agradable:

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

Ver también

+0

Gracias, Esto es lo que estaba buscando. Eso hará el truco para mí. Pregunta adicional: Mencionaste que hay una diferencia entre un método y una función: ¿cuál es la diferencia? Me gustaría saber más al respecto. ¿Me puede dar algunas referencias/enlaces donde puedo leer más al respecto? –

+3

@JohnThreepwood: los métodos en Scala se traducen en métodos en Java. Las funciones en Scala se traducen en objetos. En Scala esto es principalmente transparente (busque "* eta-expansion *"), pero a veces la sintaxis es ligeramente diferente. [Este artículo] (http://jim-mcbeath.blogspot.no/2009/05/scala-functions-vs-methods.html) es muy completo. –

+0

Genial, muchas gracias. –

8

Usando tupled, como @Tomasz menciona, es un buen enfoque.

También puede extraer la tupla devuelta por foo durante la asignación:

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

Esto tiene la ventaja de un código más limpio (sin _1 y _2), y le permite asignar nombres descriptivos para x y y, haciendo que su código más fácil de leer

+0

Gracias. Estoy de acuerdo, esto es más legible. Mantendré ese truco en mente. Pero el valor extra me molesta un poco. Me gustaría pasarlo sin guardar el resultado a un valor extra. ¡Pero aún así gracias por esta pista! –

5

Cabe también saber acerca

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

como una alternativa que no requiere que usted para crear explícitamente un temporal fooResult. Es un buen compromiso cuando la velocidad y la falta de desorden son importantes. Puede crear una función con bar _ y luego convertirla para tomar un solo argumento de tupla con .tupled, pero esto crea dos nuevos objetos de función cada vez que llama al par; podrías almacenar el resultado, pero eso podría saturar tu código innecesariamente.

Para el uso diario (es decir, esto no es la parte que limitan el rendimiento de su código), sólo puede

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

en línea.Claro, usted crea dos objetos funcionales adicionales, pero lo más probable es que haya creado la tupla también, por lo que no le importa que mucho, ¿verdad?

+0

Gracias por señalar esta alternativa. Pero, ¿por qué una tupla como valor de retorno es una señal de que no le importa el rendimiento? Pero sí, tienes razón, en mi programa el rendimiento no importa demasiado. –

+0

@JohnThreepwood - Tienes que crear un objeto para devolver una tupla. Si lo que estás haciendo es costoso en comparación con la creación de objetos, entonces probablemente también sea costoso en comparación con dos creaciones de objetos (que es lo que obtienes con 'bar _' y' .tupled'). Si lo que estás haciendo es barato en comparación con la creación de objetos, ¿por qué creaste un objeto? Deberías haber pasado en un objeto con vars que podrías establecer. (El último enfoque es algo que debe hacer rara vez, si es que lo hace, la creación de objetos es bastante barata.) –

+0

Gracias por la aclaración. La explicación tiene sentido, lo tendré en cuenta. –

Cuestiones relacionadas