8

Lors de la création d'une carte de chaînes à des fonctions partielles, j'ai rencontré un comportement inattendu. Lorsque je crée une fonction partielle en tant qu'élément cartographique, cela fonctionne correctement. Quand je l'alloue à un val, il l'invoque à la place. Essayer d'appeler la vérification génère une erreur. Est-ce prévu? Est-ce que je fais quelque chose de stupide? Commentez le check() pour voir l'invocation. J'utilise scala 2.7.7Quand une fonction partielle scala n'est pas une fonction partielle?

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 
} 
+0

Merci pour l'aide. Quand j'ai remplacé mes rêves() par des rêves() _ il s'est comporté comme je m'y attendais. Je vais sortir et lire plus sur les fonctions partielles afin que je ne mésusage pas le terme à nouveau. –

Répondre

12

Pour plus de commodité, Scala vous permet de omettez parens vides lors de l'appel d'une méthode, mais il est assez intelligent pour voir que le type attendu dans le premier cas est ()=>Unit, donc il n'a pas enlève toutes les parens pour toi; à la place, il convertit la méthode en fonction pour vous.

Dans le cas val check, cependant, il ressemble à un résultat d'appel de fonction affecté à 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 souhaitez activer la méthode en fonction, vous placez _ après la méthode en place de la liste des arguments (s). Ainsi,

val check = dream() _ 

fera ce que vous voulez.

5

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 au curry 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 n'est pas une fonction partielle, mais une fonction. Plus précisément, Function0[Unit]. Une fonction partielle aurait le 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 tâche. Scala effectue la conversion car l'inférenceur de type peut deviner le type correct.

val check = dream()   // unexpected invocation 

Ici, il n'y a aucun type attendu pour aider le type inferencer. Cependant, des listes de paramètres vides peuvent être omises, il ne s'agit donc que d'un appel de méthode.