47 votes

Composer et et puis méthodes

Je suis en suivant le tutoriel correspondant à un Modèle et fonctionnelle de la composition sur Scala compose et andThen méthodes. Il y a un exemple:

scala> def addUmm(x: String) = x + " umm"
scala> def addAhem(x: String) = x + " ahem"

val ummThenAhem = addAhem(_).compose(addUmm(_))

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

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

Toutefois, 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? N'est-ce pas la dernière expression de la même que le premier, sans parenthèse?

50voto

Daniel C. Sobral Points 159554

Eh bien, c':

addUhum _

est un eta expansion. Il convertit les méthodes en fonctions. D'autre part, ceci:

addUhum(_)

est une fonction anonyme. En fait, c'est une fonction partielle de l'application, en ce que ce paramètre n'est pas appliquée, et le tout converti en une fonction. Il s'affiche:

x => addUhum(x)

Les règles exactes pour l'expansion sont un peu difficile à expliquer, mais, fondamentalement, la fonction "start" au plus profond de l'expression délimiteur. L'exception est la fonction partielle applications, où le "x" est déplacé à l'extérieur de la fonction -- si _ est utilisé à la place d'un paramètre.

De toute façon, c'est comment il se développe:

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

Hélas, le type inferencer ne connais pas le type de x ou y. Si vous le souhaitez, vous pouvez voir exactement ce qu'il a essayé d'utiliser le paramètre -Ytyper-debug.

43voto

agilesteel Points 8330

addAhem est une méthode. compose méthode est définie sur les fonctions. addAhem _ convertit addAhem à partir de la méthode pour fonctionner, compose peut être appelée sur elle. compose s'attend à une fonction comme argument. Vous êtes en lui donnant une méthode addUmm en convertissant addUmm dans une fonction avec addUmm _ (Le trait de soulignement peut être laissé de côté parce que le compilateur peut convertir automatiquement une méthode dans une fonction quand il sait qu'une fonction est attendue de toute façon). Ainsi, votre code:

addAhem _ compose addUmm

est le même que

(addAhem _).compose(addUmm)

mais pas

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

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

5voto

4e6 Points 5970

De la documentation compose :

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

vous devez donc écrire

 scala> val ummThenAhem = (addAhem _).compose(addUmm _)
ummThenAhem: String => java.lang.String = <function1>
 

pour traiter addAhem et addUmm comme des fonctions partiellement appliquées (c'est-à-dire function1 )

 scala> addAhem _
res0: String => java.lang.String = <function1>
 

2voto

axel22 Points 17400

Je pense que le tutoriel a été écrit pour une version antérieure de Scala (probablement 2.7.7 ou antérieure). Depuis lors, il y a eu quelques changements dans le compilateur, à savoir les 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(_)
 

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