Question

Lors de la création d'une carte de chaîne à des fonctions partielles je suis tombé sur un comportement inattendu. Lorsque je crée une fonction partielle comme un élément de carte, il fonctionne très bien. Quand j'attribuer à un val, il invoque la place. En essayant d'engager la vérification génère une erreur. Est-ce prévu? Est-ce que je fais quelque chose de stupide? Commentez la check() pour voir l'invocation. J'utilise scala 2.7.7

def PartialFunctionProblem() = {
    def dream()() = {
        println("~Dream~");
        new Exception().printStackTrace()
    }
    val map = scala.collection.mutable.HashMap[String,()=>Unit]()
    map("dream") = dream()      // partial function
    map("dream")()              // invokes as expected
    val check = dream()         // unexpected invocation
    check()                     // error: check of type Unit does not take parameters 
}
Était-ce utile?

La solution

Pour plus de commodité, Scala vous permet de vider omettez parens lors de l'appel d'une méthode, mais il est assez intelligent pour voir que le type prévu dans le premier cas est ()=>Unit, il ne supprime pas tous les parens pour vous; à la place, il convertit la méthode en fonction pour vous.

Dans le val check cas, cependant, il ressemble à un résultat d'appel de fonction s'affectée à une variable. En fait, les trois d'entre eux font exactement la même chose:

val check = dream
val check = dream()
val check = dream()()

Si vous voulez transformer la méthode en fonction, vous placez _ après la méthode à la place de la liste des arguments (s) . Ainsi,

val check = dream() _

va faire ce que vous voulez.

Autres conseils

Eh bien, le problème est que vous avez tout faux. : -)

Voici quelques erreurs conceptuelles:

def dream()() = {
    println("~Dream~");
    new Exception().printStackTrace()
}

Ce n'est pas une fonction partielle. Ceci est une méthode cari avec deux listes de paramètres vides, qui renvoie Unit.

val map = scala.collection.mutable.HashMap[String,()=>Unit]()

Le type des valeurs dans cette carte ne sont pas fonction partielle, mais la fonction. Plus précisément, Function0[Unit]. Une fonction partielle aurait de type PartialFunction[T, R].

map("dream") = dream()      // partial function

Qu'est-ce qui se passe ici est que Scala convertit la méthode partiellement appliquée en fonction. Ce n'est pas une simple affectation. Scala fait la conversion parce que le type inferencer peut deviner le type correct.

val check = dream()         // unexpected invocation

Ici, il n'y a pas de type prévu pour aider le inferencer type. Cependant, des listes de paramètres vides peuvent être omises, si cela est juste un appel de méthode.

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