48 votes

Utiliser des fonctions partielles dans Scala - comment ça marche?

Je suis nouveau à la Scala, je suis en utilisant 2.9.1, et je vais essayer d'obtenir ma tête autour de la façon d'utiliser partiellement les fonctions. J'ai une compréhension de base des fonctions curryfiées, et je sais que partielle fonctions sont un peu comme des fonctions curryfiées où ils ne sont 2nary ou quelque chose du genre. Comme vous pouvez le dire, je suis un peu vert en ce.

Il semble bien que, dans certains cas, comme XML de filtrage, de pouvoir partielle des fonctions serait hautement profitable, donc je suis en espérant obtenir une meilleure compréhension de la façon de les utiliser.

J'ai une fonction qui utilise la règle qui la structure, mais j'en ai besoin pour travailler avec deux arguments, alors que la règle qui la structure ne prend qu'un seul, OU une fonction partielle. Je pense que c'est le cas, je pense m'être utile.

Des conseils, des liens, des mots de sagesse etc. bienvenue!

Les réponses sont excellentes, et ont dégagé quelques fondamentaux de fausses idées que j'ai. Je pense qu'ils ont également expliquer d'où je suis en difficulté, je pense, peut-être de poster une nouvelle question d'être un peu plus spécifique va l'aider, alors je vais le faire aussi.

143voto

Rex Kerr Points 94401

Une fonction partielle est une fonction qui n'est valable que pour un sous-ensemble de valeurs de ces types, vous risquez de passer pour elle. Par exemple:

val root: PartialFunction[Double,Double] = {
  case d if (d >= 0) => math.sqrt(d)
}

scala> root.isDefinedAt(-1)
res0: Boolean = false

scala> root(3)
res1: Double = 1.7320508075688772

Ceci est utile lorsque vous avez quelque chose qui sait comment faire pour vérifier si une fonction est définie ou non. Recueillir, par exemple:

scala> List(0.5, -0.2, 4).collect(root)   // List of _only roots which are defined_
res2: List[Double] = List(0.7071067811865476, 2.0)

Ce n'est pas va vous aider à placer les deux arguments où vous voulez vraiment un.

En revanche, une application partielle de la fonction est une fonction où certains de ses arguments ont déjà été remplie.

def add(i: Int, j: Int) = i + j
val add5 = add(_: Int,5)

Maintenant vous avez seulement besoin d'un argument-la chose à ajouter 5 à--au lieu de deux:

scala> add5(2)
res3: Int = 7

Vous pouvez le voir sur cet exemple comment l'utiliser.

Mais si vous avez besoin de spécifier ces deux arguments, ce encore de ne pas le faire--dire que vous souhaitez utiliser map, par exemple, et vous devez lui donner une fonction à un argument, mais vous souhaitez ajouter deux choses différentes. Eh bien, alors vous pouvez

val addTupled = (add _).tupled

qui sera partiellement appliquer la fonction (vraiment, il suffit de créer une fonction de la méthode, puisque rien n'a été rempli) et puis de combiner les différents arguments dans un tuple. Maintenant, vous pouvez l'utiliser dans des endroits qui nécessitent un seul argument (en supposant que le type est correct):

scala> List((1,2), (4,5), (3,8)).map(addTupled)
res4: List[Int] = List(3, 9, 11)

En revanche, le nourrissage est différent encore une fois, il tourne les fonctions de la forme (A,B) => C en A => B => C. C'est, compte tenu d'une fonction de plusieurs arguments, il va produire une chaîne de fonctions qui prennent chacun un argument et de retourner une chaîne d'un plus court (vous pouvez la considérer comme partiellement l'application de l'un argument à la fois).

val addCurried = (add _).curried

scala> List(1,4,3).map(addCurried)
res5: List[Int => Int] = List(<function1>, <function1>, <function1>)

scala> res5.head(2)   // is the first function, should add 1
res6: Int = 3

scala> res5.tail.head(5)   // Second function should add 4
res7: Int = 9

scala> res5.last(8)  // Third function should add 3
res8: Int = 11

35voto

Daniel C. Sobral Points 159554

Rex Kerr explication est très bien-et pas de surprise non plus. La question est clairement le mélange jusqu' partielle des fonctions avec application partielle de fonctions. Pour ce que ça vaut la peine, j'ai fait la même confusion moi-même lorsque j'ai appris la Scala.

Cependant, la question ne attirer l'attention sur partielles de fonctions, j'aimerais en parler un peu.

Beaucoup de gens disent que partielle fonctions sont des fonctions qui ne sont pas définis pour toutes les entrées, et c'est vrai pour les mathématiques, mais pas de la Scala. En Scala, une fonction ne peut pas être définie pour toutes les contributions qui soit. En fait, depuis partielle de la fonction d'hériter de la fonction, la fonction comprend toutes les partielles de fonctions, ce qui le rend inévitable.

D'autres mentionnent la méthode isDefinedAt, ce qui est, en effet, une différence, mais surtout sur la mise en œuvre. C'est tellement vrai que la Scala 2.10 sera probablement libéré avec un "fast partiel de la fonction", qui ne repose pas sur isDefinedAt.

Et quelques personnes même implique que l' apply méthode partielle des fonctions de faire quelque chose de différent que l' apply méthode pour les fonctions, comme exécutant uniquement pour l'entrée définie -- qui ne pouvait pas être plus éloigné de la vérité. L' apply méthode est exactement la même.

Quel partielle des fonctions vraiment venir au fond, c'est une autre méthode: orElse. Qui résume tous les cas d'utilisation partielle des fonctions beaucoup mieux que d' isDefinedAt, parce que partielle fonctions sont vraiment au sujet de faire une des choses suivantes:

  • Le chaînage partiel des fonctions (qui est ce que l' orElse t), de sorte qu'une entrée sera essayé sur chaque fonction partielle jusqu'à ce que l'un d'entre eux correspond.
  • Faire quelque chose de différent si une fonction partielle ne correspond pas, au lieu de lancer une exception, qui est ce qui se passerait si vous avez de la chaîne qu'autre chose à l'aide de orElse.

Je ne dis pas que tout peut être facilement mis en œuvre en termes de orElse, vous l'esprit. Je dis juste que partielle fonctions sont de faire quelque chose d'autre quand une entrée n'est pas définie pour elle.

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