55 votes

Utilité (comme dans les applications pratiques) de Currying vs Application partielle à Scala

J'essaie de comprendre les avantages du currying par rapport aux applications partielles dans Scala. Veuillez considérer le code suivant:

   def sum(f: Int => Int) = (a: Int, b: Int) => f(a) + f(b)

  def sum2(f: Int => Int, a: Int, b: Int): Int = f(a) + f(b)

  def sum3(f: Int => Int)(a: Int, b: Int): Int = f(a) + f(b)

  val ho = sum({identity})
  val partial = sum2({ identity }, _, _)
  val currying = sum3({ identity })

  val a = currying(2, 2)
  val b = partial(2, 2)
  val c = ho(2, 2)
 

Donc, si je peux calculer aussi facilement une fonction partiellement appliquée, quels sont les avantages du curry?

101voto

Martin Odersky Points 13161

Nourrissage est principalement utilisée si le second paramètre de la section est une fonction ou un paramètre de nom. Cela a deux avantages. Tout d'abord, l'argument de fonction peut alors ressembler à un bloc de code entre accolades. E. g.

using(new File(name)) { f =>
  ...
}

Cela se lit mieux que le uncurried alternative:

using(new File(name), f => {
  ...
})

Deuxièmement, et plus important, l'inférence de type peut généralement comprendre la fonction du paramètre du type, de sorte qu'il n'a pas à être donné sur le site d'appel. Par exemple, si je définis max de la fonction sur les listes comme ceci:

def max[T](xs: List[T])(compare: (T, T) => Boolean)

Je peux l'appeler comme ceci:

max(List(1, -3, 43, 0)) ((x, y) => x < y)

ou encore plus court:

max(List(1, -3, 43, 0)) (_ < _)

Si je définis max comme un uncurried fonction, cela ne fonctionnerait pas, je serais obligé de l'appeler comme ceci:

max(List(1, -3, 43, 0), (x: Int, y: Int) => x < y)

Si le dernier paramètre est pas une fonction ou le paramètre de nom, je ne conseillerais pas les lancer. Scala _ notatation est amost comme léger, plus souple et plus claire de l'OMI.

6voto

Debilski Points 28586

Je pense que cela devient plus clair si vous inversez votre curry exemple:

def sum4(a: Int, b: Int)(f: Int => Int): Int = f(a) + f(b)

val d = sum4(2, 2) { x =>
  x * x
}

Il s'agit plus d'un effet d'optique, mais vous n'avez pas besoin d'utiliser des parenthèses autour de l'expression entière. Bien sûr, vous pouvez obtenir le même résultat à l'aide de l'application partielle ou par la création d'une méthode d'aide à inverser les arguments, c'est sûr. Le point est, que vous n'avez pas à faire tout cela si vous commencez avec un curry de méthode dans la première place. En ce sens, nourrissage est plus d'une API et la syntaxe de sucre chose. Il n'est pas prévu que vous utilisez

val partial_sum4 = sum4(2, 2)

n'importe où dans votre code ou que ce n'est en aucune façon particulièrement utile à faire. C'est juste que vous obtenez un bien à la recherche de l'expression facilement.

(Bien, et il y a certains avantages à l'égard de l'inférence de type...)

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