scala parameters tuples

scala tuple desempacando



parameters tuples (5)

Sé que esta pregunta ha surgido muchas veces de diferentes maneras. Pero todavía no está claro para mí. ¿Hay alguna manera de lograr lo siguiente?

def foo(a:Int, b:Int) = {} foo(a,b) //right way to invoke foo foo(getParams) // is there a way to get this working without explicitly unpacking the tuple?? def getParams = { //Some calculations (a,b) //where a & b are Int }


@ dave-griffith está muerto.

También puedes llamar:

Function.tupled(foo _)

Si quieres adentrarte en "mucho más información de la que pedí" territorio, también hay métodos integrados en funciones parcialmente aplicadas (y en Function ) para currying. Algunos ejemplos de entrada / salida:

scala> def foo(x: Int, y: Double) = x * y foo: (x: Int,y: Double)Double scala> foo _ res0: (Int, Double) => Double = <function2> scala> foo _ tupled res1: ((Int, Double)) => Double = <function1> scala> foo _ curried res2: (Int) => (Double) => Double = <function1> scala> Function.tupled(foo _) res3: ((Int, Double)) => Double = <function1> // Function.curried is deprecated scala> Function.curried(foo _) warning: there were deprecation warnings; re-run with -deprecation for details res6: (Int) => (Double) => Double = <function1>

Donde se invoca la versión curried con múltiples listas de argumentos:

scala> val c = foo _ curried c: (Int) => (Double) => Double = <function1> scala> c(5) res13: (Double) => Double = <function1> scala> c(5)(10) res14: Double = 50.0

Finalmente, también puede desajustar / destrabar si es necesario. Function tiene edificaciones integradas para esto:

scala> val f = foo _ tupled f: ((Int, Double)) => Double = <function1> scala> val c = foo _ curried c: (Int) => (Double) => Double = <function1> scala> Function.uncurried(c) res9: (Int, Double) => Double = <function2> scala> Function.untupled(f) res12: (Int, Double) => Double = <function2>


Ahora, puedes implementar foo y hacerlo tomar un parámetro de la clase Tuple2 como tal.

def foo(t: Tuple2[Int, Int]) = { println("Hello " + t._1 + t._2) "Makes no sense but ok!" } def getParams = { //Some calculations val a = 1; val b = 2; (a, b) //where a & b are Int } // So you can do this! foo(getParams) // With that said, you can also do this! foo(1, 3)


Aprecio algunas de las otras respuestas que estaban más cerca de lo que pediste, pero me resultó más fácil para un proyecto actual agregar otra función que convierta los parámetros de tupla en los parámetros de división:

def originalFunc(a: A, b: B): C = ... def wrapperFunc(ab: (A, B)): C = (originalFunc _).tupled(ab)


Es un procedimiento de dos pasos. Primero convierte foo en una función, luego llama a tupled para que sea una función de una tupla.

(foo _).tupled(getParams)


Function.tupled(foo _)(getParams) o el sugerido por Dave.

EDITAR:

Para responder a tu comentario:

¿Qué pasa si foo resulta ser el constructor de alguna clase?

En ese caso, este truco no funcionará.

Puede escribir un método de fábrica en el objeto complementario de su clase y luego obtener la versión en tupla de su método de apply utilizando una de las técnicas antes mencionadas.

scala> class Person(firstName: String, lastName: String) { | override def toString = firstName + " " + lastName | } defined class Person scala> object Person { | def apply(firstName: String, lastName: String) = new Person(firstName, lastName) | } defined module Person scala> (Person.apply _).tupled(("Rahul", "G")) res17: Person = Rahul G

Con las case class obtienes un objeto complementario con un método de apply forma gratuita, y por lo tanto, esta técnica es más conveniente de usar con case class .

scala> case class Person(firstName: String, lastName: String) defined class Person scala> Person.tupled(("Rahul", "G")) res18: Person = Person(Rahul,G)

Sé que es mucha duplicación de código, pero lamentablemente ... ¡todavía no tenemos macros! ;)