Je sais que cette question a été soulevée de nombreuses fois de différentes manières. Mais ce n’est toujours pas clair pour moi. Y a-t-il un moyen d’atteindre ce qui suit?
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 }
C’est une procédure en deux étapes. Tournez d’abord foo dans une fonction, puis appelez tupled sur elle pour en faire une fonction d’un tuple.
(foo _).tupled(getParams)
@ dave-griffith est mort.
Vous pouvez également appeler:
Function.tupled(foo _)
Si vous voulez vous promener dans le territoire “beaucoup plus d’informations que j’ai demandé”, il existe également des méthodes intégrées dans les fonctions partiellement appliquées (et sur la Function
) pour le curry. Quelques exemples d’entrées / sorties:
scala> def foo(x: Int, y: Double) = x * y foo: (x: Int,y: Double)Double scala> foo _ res0: (Int, Double) => Double = scala> foo _ tupled res1: ((Int, Double)) => Double = scala> foo _ curried res2: (Int) => (Double) => Double = scala> Function.tupled(foo _) res3: ((Int, Double)) => Double = // Function.curried is deprecated scala> Function.curried(foo _) warning: there were deprecation warnings; re-run with -deprecation for details res6: (Int) => (Double) => Double =
La version au curry est appelée avec plusieurs listes d’arguments:
scala> val c = foo _ curried c: (Int) => (Double) => Double = scala> c(5) res13: (Double) => Double = scala> c(5)(10) res14: Double = 50.0
Enfin, vous pouvez également décortiquer / décomposer si nécessaire. Function
a des Function
intégrées pour cela:
scala> val f = foo _ tupled f: ((Int, Double)) => Double = scala> val c = foo _ curried c: (Int) => (Double) => Double = scala> Function.uncurried(c) res9: (Int, Double) => Double = scala> Function.untupled(f) res12: (Int, Double) => Double =
Function.tupled(foo _)(getParams)
ou celui suggéré par Dave.
MODIFIER:
Pour répondre à votre commentaire:
Et si foo est le constructeur d’une classe?
Dans ce cas, cette astuce ne fonctionnera pas.
Vous pouvez écrire une méthode d’usine dans l’object compagnon de votre classe, puis obtenir la version tuplée de sa méthode d’ apply
utilisant l’une des techniques susmentionnées.
scala> class Person(firstName: Ssortingng, lastName: Ssortingng) { | override def toSsortingng = firstName + " " + lastName | } defined class Person scala> object Person { | def apply(firstName: Ssortingng, lastName: Ssortingng) = new Person(firstName, lastName) | } defined module Person scala> (Person.apply _).tupled(("Rahul", "G")) res17: Person = Rahul G
Avec la case class
es, vous obtenez un object compagnon avec une méthode d’application gratuite, et cette technique est donc plus pratique à utiliser avec les case class
es.
scala> case class Person(firstName: Ssortingng, lastName: Ssortingng) defined class Person scala> Person.tupled(("Rahul", "G")) res18: Person = Person(Rahul,G)
Je sais que c’est beaucoup de duplication de code mais hélas … nous n’avons pas encore de macros! 😉
J’apprécie certaines des autres réponses qui étaient plus proches de ce que vous aviez demandé, mais j’ai trouvé plus facile pour un projet en cours d’append une autre fonction qui convertit les parameters de tuple en parameters fractionnés:
def originalFunc(a: A, b: B): C = ... def wrapperFunc(ab: (A, B)): C = (originalFunc _).tupled(ab)
Maintenant, vous pouvez implémenter foo et lui faire prendre un param de la classe Tuple2 comme ça.
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)