90 votes

scala tuple déballage

Je sais que cette question a été posée à plusieurs reprises de différentes manières. Mais ce n'est toujours pas clair pour moi. Y a-t-il un moyen de réaliser 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
}
 

104voto

Dave Griffith Points 12923

C'est une procédure en deux étapes. Commencez par transformer foo en une fonction, puis appelez-la plusieurs fois pour la transformer en fonction d'un tuple.

 (foo _).tupled(getParams)
 

55voto

Brendan W. McAdams Points 4849

@dave-griffith est mort sur.

Vous pouvez aussi appeler:

Function.tupled(foo _)

Si vous voulez flâner dans la "voie à plus d'information que j'ai demandé" un territoire, il existe également des méthodes intégrées partiellement appliquée fonctions (et sur Function) pour le nourrissage. Quelques-uns d'entrée/sortie des exemples:

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>

Dans lequel la au curry version est invoqué avec plusieurs listes d'arguments:

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

Enfin, vous pouvez également uncurry/untuple si nécessaire. Function a les builtins pour cela:

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>

20voto

missingfaktor Points 44003

Function.tupled(foo _)(getParams) ou celui proposé par Dave.

EDIT:

Pour répondre à votre commentaire:

Que faire si toto se trouve être le constructeur de la classe?

Dans ce cas, cette astuce ne fonctionne pas.

Vous pouvez écrire une méthode de fabrique dans le compagnon objet de votre classe, puis obtenir l'tupled version de son apply méthode à l'aide de ces techniques.

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

Avec case classes, vous obtenez un compagnon de l'objet avec un apply méthode de gratuitement, et donc cette technique est plus pratique à utiliser avec case classes.

scala> case class Person(firstName: String, lastName: String)
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 les macros (encore)! ;)

3voto

xen Points 36

J'apprécie certaines des réponses plus proches de ce que vous avez demandé, mais j'ai trouvé plus facile pour un projet en cours d'ajouter une autre fonction qui convertit les paramètres de tuple en paramètres de division:

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

1voto

Rejinderi Points 3584

Maintenant, vous pouvez implémenter foo et lui faire prendre un param de la classe Tuple2 comme ceci.

 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)
 

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X