He leído varios tutoriales de Java 8 antes.
En este momento me encontré con el siguiente tema: ¿Java es compatible con Currying?
Aquí, veo el siguiente código:
IntFunction<IntUnaryOperator> curriedAdd = a -> b -> a + b;
System.out.println(curriedAdd.apply(1).applyAsInt(12));
Entiendo que este ejemplo suma 2 elementos pero no puedo entender la construcción:
a -> b -> a + b;
Según la parte izquierda de la expresión, esta fila debe implementar la siguiente función:
R apply(int value);
Antes de esto, solo conocía lambdas con una sola flecha.
Respuestas:
Si expresa esto como sintaxis lambda no abreviada o sintaxis de clase anónima Java pre-lambda, es más claro lo que está sucediendo ...
La pregunta original. ¿Por qué hay dos flechas? Simple, se están definiendo dos funciones ... La primera función es una función que define una función, la segunda es el resultado de esa función, que también es función. Cada uno requiere un
->
operador para definirlo.No taquigrafía
Pre-Lambda antes de Java 8
fuente
final int value
pre-lambda
An
IntFunction<R>
es una funciónint -> R
. AnIntUnaryOperator
es una funciónint -> int
.Por tanto, an
IntFunction<IntUnaryOperator>
es una función que toma anint
como parámetro y devuelve una función que toma anint
como parámetro y devuelve anint
.Tal vez sea más claro si usa clases anónimas para "descomponer" el lambda:
fuente
Agregar paréntesis puede aclarar esto:
O probablemente la variable intermedia pueda ayudar:
fuente
Reescribamos esa expresión lambda entre paréntesis para que quede más claro:
Entonces estamos declarando una función tomando an
int
que devuelve aFunction
. Más específicamente, la función devuelta toma anint
y devuelve anint
(la suma de los dos elementos): esto se puede representar como anIntUnaryOperator
.Por lo tanto,
curriedAdd
es una función que toma unaint
y devuelve unaIntUnaryOperator
, por lo que se puede representar comoIntFunction<IntUnaryOperator>
.fuente
Son dos expresiones lambda.
fuente
Si lo miras
IntFunction
, podría ser más claro:IntFunction<R>
es unFunctionalInterface
. Representa una función que tomaint
y devuelve un valor de tipoR
.En este caso, el tipo de retorno
R
también es aFunctionalInterface
, es decir, anIntUnaryOperator
. Entonces, la primera función (externa) en sí misma devuelve una función.En este caso: cuando se aplica a an
int
,curriedAdd
se supone que devuelve una función que vuelve a tomar anint
(y vuelve de nuevoint
, porque eso es lo queIntUnaryOperator
hace).En la programación funcional, es común escribir el tipo de función como
param -> return_value
y ve exactamente eso aquí. Entonces el tipo decurriedAdd
esint -> int -> int
(oint -> (int -> int)
si te gusta más).La sintaxis lambda de Java 8 va de la mano con esto. Para definir tal función, escribe
que es muy similar al cálculo lambda real:
λb a + b
es una función que toma un solo parámetrob
y devuelve un valor (la suma).λa λb a + b
es una función que acepta un solo parámetroa
y devuelve otra función de un solo parámetro.λa λb a + b
vuelveλb a + b
cona
establecido en el valor del parámetro.fuente