Las clausuras o closures son funciones lambda que acceden a un "contexto".
Cualquier lambda en cualquier lenguaje con Garbage Collection (Java, C#, Javascript, Haskell, Scala, etc...) casi seguro es también una closure. En el caso de Rust (y de C++?) la "clausura" y el "lambda" se diferencian.
Las clausuras son funcionalmente equivalentes a las clases. Es fácil traducir una clase a una función que devuelve una clausura y viceversa. Veamos un ejemplo en javascript:
function newCounter() {
let count = 0
return {
getValue: () => count,
increase: () => count = count + 1
}
}
class Counter {
private count = 0
getValue() {
return this.count
}
increase() {
return this.count = this.count + 1
}
}
/* Devuelven un objeto equivalente. */
newCounter()
new Counter()
Al llamar a la función newCounter
, se crea un contexto (scope) en el que se pueden definir variables.
Imaginemos al scope como un objeto JSON. Al comienzo está vacío: {}
.
Luego de leer la sentencia let count = 0
, el scope tiene esta forma: { count: 0 }
.
Los lambdas () => count
y () => count = count + 1
crean clausuras (clousures) que capturan una referencia a ese scope.
Cada vez que se llama a la función newCounter
se crea un scope nuevo. O sea que si creamos dos contadores diferentes,
incrementar el valor de uno no afecta el valor del otro.