Question

Y at-il une façon scala pour obtenir les arguments de retour d'une fonction appliquée déjà en partie?

Est-ce même du sens, devrait être fait, ou se insère dans tous les cas d'utilisation?

exemple:

def doStuff(lower:Int,upper:Int,b:String)= for(turn <- lower to upper) println(turn +": "+b)

Imaginez qu'à un moment donné, je sais que l'argument « inférieur » et je reçois une fonction de l'appliquer à « doStuff »

val lowerDoStuff = doStuff(3,_:Int,_:String)

est-il pour moi un moyen d'obtenir que 3 de retour? (Par souci d'exemple, imaginez que je suis dans une fonction qui n'a reçu « lowerDoStuff » et doit maintenant connaître le premier argument)

Idiomatic Scala est préféré à l'introspection / réflexion (si possible).

Était-ce utile?

La solution

idiomatiques Scala: non, vous ne pouvez pas. Vous avez dit spécifiquement que le premier argument n'est plus pertinent. Si le compilateur peut faire disparaître tout à fait, qui est le mieux: vous dites que vous avez une fonction qui dépend d'un int et une chaîne, et vous n'avez pas fait des promesses au sujet de ce qui a généré. Si vous vraiment besoin de cette valeur, mais vous avez vraiment besoin de passer une fonction 2 argument, vous pouvez le faire à la main:

class Function2From3[A,B,C,Z](f: (A,B,C) => Z, val _1: A) extends Function2[B,C,Z] {
  def apply(b: B, c: C) = f(_1, b, c)
}
val lowerDoStuff = new Function2From3(doStuff _, 3)

Maintenant, quand vous obtenez la fonction plus tard, vous pouvez match de modèle pour voir si elle est un Function2From3, puis lisez la valeur:

val f: Function2[Int,String,Unit] = lowerDoStuff
f match {
  case g: Function2From3[_,_,_,_] => println("I know there's a "+g._1+" in there!")
  case _ => println("It's all Greek to me.")
}

(s'il est important pour vous que ce soit un entier, vous pouvez supprimer A comme paramètre générique et faire _1 être un entier - et peut-être juste l'appeler lower pendant que vous y êtes).

Réflexion: non, vous ne pouvez pas (pas en général). Le compilateur est plus intelligent que ça. Le bytecode généré (si nous emballons votre code class FuncApp) est:

public final void apply(int, java.lang.String);
  Signature: (ILjava/lang/String;)V
  Code:
   0:   aload_0
   1:   getfield    #18; //Field $outer:LFuncApp;
   4:   iconst_3
   5:   iload_1
   6:   aload_2
   7:   invokevirtual   #24; //Method FuncApp.doStuff:(IILjava/lang/String;)V
   10:  return

Notez que le iconst_3? C'est là votre 3 est allé - il a disparu dans le bytecode. Il n'y a même pas un champ privé caché contenant la valeur plus.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top