Composer et puis Méthodes

Je suis le tutoriel La correspondance des motifs et la composition fonctionnelle sur la composition de Scala et les méthodes. Voici un exemple:

 scala> def addUmm(x: Ssortingng) = x + " umm" scala> def addAhem(x: Ssortingng) = x + " ahem" val ummThenAhem = addAhem(_).compose(addUmm(_)) 

Lorsque j’essaie de l’utiliser, j’obtiens une erreur:

 :7: error: missing parameter type for expanded function ((x$1) => addAhem(x$1).compose(((x$2) => addUmm(x$2)))) val ummThenAhem = addAhem(_).compose(addUmm(_)) ^ :7: error: missing parameter type for expanded function ((x$2) => addUmm(x$2)) val ummThenAhem = addAhem(_).compose(addUmm(_)) ^ :7: error: type mismatch; found : java.lang.Ssortingng required: Int val ummThenAhem = addAhem(_).compose(addUmm(_)) 

Cependant, cela fonctionne:

 val ummThenAhem = addAhem _ compose addUmm _ 

ou même

 val ummThenAhem = addAhem _ compose addUmm 

Quel est le problème avec le code dans le tutoriel? Cette dernière expression n’est-elle pas la même que la première sans parenthèse?

addAhem est une méthode. compose méthode de compose est définie sur les fonctions. addAhem _ convertit addAhem de la méthode à la fonction, donc compose peut être appelé dessus. compose attend une fonction comme argument. Vous lui donnez une méthode addUmm en convertissant addUmm en une fonction avec addUmm _ (Le trait de soulignement peut être addUmm _ car le compilateur peut convertir automatiquement une méthode en une fonction quand elle sait qu’une fonction est de toute façon attendue). Donc votre code:

 addAhem _ compose addUmm 

est le même que

 (addAhem _).compose(addUmm) 

mais non

 addAhem(_).compose(addUmm(_)) 

PS Je n’ai pas regardé le lien que vous avez fourni.

Bon ça:

 addUhum _ 

est une expansion d’eta. Il convertit les méthodes en fonctions. En revanche, ceci:

 addUhum(_) 

est une fonction anonyme. En fait, il s’agit d’une application partielle, dans la mesure où ce paramètre n’est pas appliqué, et le tout converti en une fonction. Il s’étend à:

 x => addUhum(x) 

Les règles exactes pour l’expansion sont un peu difficiles à expliquer, mais, fondamentalement, la fonction “démarrera” au délimiteur d’expression le plus interne. L’exception concerne les applications de fonctions partielles, où le “x” est déplacé en dehors de la fonction – si _ est utilisé à la place d’un paramètre.

En tout cas, voici comment cela se développe:

 val ummThenAhem = x => addAhem(x).compose(y => addUmm(y)) 

Hélas, l’inférence de types ne connaît pas le type de x ou y. Si vous le souhaitez, vous pouvez voir exactement ce qu’il a essayé en utilisant le paramètre -Ytyper-debug .

De la documentation de compose :

Compose deux instances de Function1 dans une nouvelle fonction1, cette fonction étant appliquée en dernier.

alors vous devriez écrire

 scala> val ummThenAhem = (addAhem _).compose(addUmm _) ummThenAhem: Ssortingng => java.lang.Ssortingng =  

traiter addAhem et addUmm comme des fonctions partiellement appliquées (ie function1 )

 scala> addAhem _ res0: Ssortingng => java.lang.Ssortingng =  

Je pense que le tutoriel a été écrit pour une version antérieure de Scala (probablement 2.7.7 ou antérieure). Depuis, des modifications ont été apscopes au compilateur, à savoir des extensions du système de types, qui entraînent désormais l’échec de l’inférence de type sur:

 addUhum(_).compose(addAhem(_)) 

Le levage vers une fonction fonctionne toujours avec cette syntaxe si vous écrivez simplement:

 addUhum(_)