Utilidad (como en aplicaciones prácticas) de Currying vs Parial Application en Scala

Estoy tratando de entender las ventajas de currying sobre aplicaciones parciales en Scala. Por favor considere el siguiente código:

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) 

Entonces, si puedo calcular la función parcialmente aplicada tan fácil, ¿cuáles son las ventajas de currying?

El currying se usa principalmente si la sección del segundo parámetro es una función o un parámetro de nombre. Esto tiene dos ventajas. Primero, el argumento de la función puede verse como un bloque de código entre llaves. P.ej

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

Esto se lee mejor que la alternativa incierta:

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

En segundo lugar, y lo que es más importante, la inferencia de tipo generalmente puede determinar el tipo de parámetro de la función, por lo que no tiene que darse en el sitio de la llamada. Por ejemplo, si defino una función max sobre listas como esta:

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

Puedo llamarlo así:

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

o incluso más corto:

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

Si definiera max como una función no comprobada, esto no funcionaría, tendría que llamarlo así:

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

Si el último parámetro no es una función o un parámetro de nombre, no recomendaría currying. La notación de Scala es casi tan ligera, más flexible e IMO más clara.

Creo que se vuelve más claro si inviertes tu ejemplo al curry:

 def sum4(a: Int, b: Int)(f: Int => Int): Int = f(a) + f(b) val d = sum4(2, 2) { x => x * x } 

Es más un efecto óptico, pero no es necesario usar ningún paréntesis alrededor de toda la expresión. Por supuesto, puede lograr el mismo resultado utilizando una aplicación parcial o creando un método auxiliar para invertir los argumentos, claro. El punto es que no tienes que hacer todo esto si comienzas con un método de curry en primer lugar. En ese sentido, currying es más una cosa de azúcar API y syntax. No se espera que uses

 val partial_sum4 = sum4(2, 2) 

en cualquier parte de tu código o que esto sea de alguna manera especialmente significativo para hacer. Es solo que obtienes una expresión que se ve bien con facilidad.

(Bueno, y hay algunas ventajas con respecto a la inferencia de tipo …)