0% encontró este documento útil (0 votos)
25 vistas13 páginas

Closures

Las closures permiten emular la programación funcional, igualar funciones con variables, capturar estados del programa y manipular funciones callbacks. Se implementan capturando las variables necesarias para ejecutarse desde el ámbito donde fueron definidas. Muchos lenguajes como ML, Lisp, JavaScript, Rust y Go incluyen closures.

Cargado por

Agustina Alabart
Derechos de autor
© © All Rights Reserved
Nos tomamos en serio los derechos de los contenidos. Si sospechas que se trata de tu contenido, reclámalo aquí.
Formatos disponibles
Descarga como PDF, TXT o lee en línea desde Scribd
0% encontró este documento útil (0 votos)
25 vistas13 páginas

Closures

Las closures permiten emular la programación funcional, igualar funciones con variables, capturar estados del programa y manipular funciones callbacks. Se implementan capturando las variables necesarias para ejecutarse desde el ámbito donde fueron definidas. Muchos lenguajes como ML, Lisp, JavaScript, Rust y Go incluyen closures.

Cargado por

Agustina Alabart
Derechos de autor
© © All Rights Reserved
Nos tomamos en serio los derechos de los contenidos. Si sospechas que se trata de tu contenido, reclámalo aquí.
Formatos disponibles
Descarga como PDF, TXT o lee en línea desde Scribd
Está en la página 1/ 13

Closures

¿Qué son? Unidades + datos que necesita para ejecutarse


¿Para qué sirven? ● Emular la programación funcional
● Igualar funciones con variables
● Capturar estados del programa
● Emular encapsulamiento de datos
● Manipular funciones callbacks
● Implementar funciones asincrónicas
en programación Reactiva
¿Cómo se implementan? Dirección de unidad + mecanismo de captura de datos

¿Cuáles lenguajes tienen ML, Lisp, Perl, Ruby, Python, Javascript, PHP, C++14,
closures? Java8+, C#, Rust, Go, etc.
Closures
Función usada en un ámbito diferente al cual fue definida
Las variables que necesita pueden no estar presentes en el ámbito de uso
El lenguaje debe proveer un mecanismo para que la función acceda a las
variables que necesita

fn function f1() {
¿Cómo hace la función f2
int x;
para acceder a la variable
fn function f2(){ Es necesario “capturar” x
x cuando se ejecute sin
print x; para que f2 pueda
que esté en memoria la
} funcionar correctamente
variable x?
return f2; fuera de f1
};
int main() {
z=f1(); Se está invocando a f2 fuera
z(); de f1
}
Ejemplos de Closures

Rust
fn main() { Se construye un closure que utiliza la
let mut num = 5; variable num
{
let mut add_num = move
|x: i32| num+= x; Ejecución de closure add_num

add_num(5); ¿Cuál es el valor de num luego de la


} ejecución del closure?
println!("num: {}", num);
}
Ejemplos de Closures

Javascript Se construye un closure que utiliza la


function fn() { variable x
var x = 3;
var lambdaFun = () => x+1; Ejecución de closure lambdaFun
x++;
console.log(lambdaFun());
console.log(x); ¿Cuál es el valor de x luego de la
} ejecución del closure?
Ejemplos de Closures

R Recibe una función como parámetro


stat <- function(stat_name){
function(x){
stat_name(x) Retorna un closure que usa la
} función stat_name()
}

mean_of_x <- stat(mean)


sd_of_x <- stat(sd) Closures recibidos de stat
mean_of_x(x)
sd_of_x(x)

Ejecución de closures recibidos


Captura en Lenguajes tipo Algol
¿Cómo se resuelve el ámbito de los closures en lenguajes de tipo Algol?

fn function f1() {
int x=1;
fn function f2(){ f1 f2 / z
x 1
print x;
}
return f2;
}; main La variable x ya no está disponible
z 1
int main() {
z=f1();

¿Cómo se captura “x” para que el closure pueda utilizarla?
z();
} ● Por copia ¿Dónde se ubica la copia?

● Por referencia ¿Qué sucede con la celda referenciada?


Captura en Lenguajes tipo Algol
C++
#include <stdio.h>
static int global=1;
auto f() { cl1
int nolocal=2; f nolocal 2 local 3
printf("&nolocal en creadora: %d \n",&nolocal);
auto func = [=] () {
int local= 3; cl1 2
printf("&local en closure: %d \n",&local);
printf("&nolocal en closure: %d \n",&nolocal);
main
printf("&global en closure: %d \n",&global); localmain 4
};
return func; Var.
} global 1
int main() { Est.
int localmain = 4;
auto cl1= f(); ● Las variables se capturan por copia.
cl1();
cl1();
● Las copias se almacenan en la variable
printf("&localmain en main: %d \n",&localmain); receptora (en el registro de activación
printf("&cl1 en main: %d \n",&cl1); de la unidad receptora)
}
Captura en Lenguajes tipo Algol
Rust
static mut w : i32 = 1; $1000 x 2
HEAP
fn f() -> Box<dyn FnMut()> { código $320
let mut x = 2;
return Box::new(move || {
let mut z : i32 = x;
unsafe { parámetro 1000
println!("&w &x &z: {:p}, {:p}, {:p}",&w,&x,&z);
} f c1
x 2 z 2
});
}

fn main() c1 1000
{ main
let mut c1=f(); y 0
let mut y = 0;
c1(); ● Las variables se capturan por copia.
println!("&c1:{:p}",&c1); ● Las copias se almacenan en el heap y la
println!("c1:{:p}",c1);
println!("&y:{:p}",&y);
variable receptora (en el registro de
} activación de la unidad receptora) es un
puntero
Captura en Lenguajes tipo Algol
Go
package main
import "fmt"
var w int = 1
c1 z 2
func f1() func() { ● Las variables se capturan por
var x int = 2
fmt.Printf("\n &x en f1:",&x);
referencia.
return func() { ● Con este modelo de pila no es
f1
var z int = x x 2 necesario realizar una copia
fmt.Printf("\n &w:",&w);
fmt.Printf("\n &x:",&x); porque el registro de
fmt.Printf("\n &z:",&z); activación donde está la
} c1 $350
} main variable capturada, permanece
y 0 en memoria
func main() {
var c1 = f1();
var y = 0;
c1();
Puntero al código del
fmt.Printf("\n &c1: \n",&c1); closure
fmt.Printf("\n &y: \n",&y);
}
Efectos laterales y sensibilidad a la historia
Go
package main
import "fmt" ¿Qué imprime este programa?
var k int = 1

func f() func() {


var i int = 3 ¿El lenguaje tiene efectos laterales?
return func() {
var j int = 5 Si, la ejecución de un closure afecta
fmt.Printf("",i+j+k);
i = i + 1; otras partes del programa (por la
j = j + 1; modificación de k)
k = k + 1;
} ¿El lenguaje tiene sensibilidad a la historia?
}
9 Si, la ejecución de un closure afecta
func main() {
a := f(); sucesivas ejecuciones del mismo
a();
11
closure (por la modificación de la
a();
b := f();
13 variable capturada i)
a();
b(); 12
}
Efectos laterales y sensibilidad a la historia
C++ error: increment of read-only variable ‘nolocal’
#include <stdio.h>
¿Estos lenguajes
static int global=1; Java
auto f() { tienen efectos class CreadoraClosures {
int nolocal=2; laterales? int at1=1;
auto func = [=] () { static int ac1=2;
int local= 3; Si, la ejecución de un Function<Integer,Integer> devuelveFunction() {
nolocal++; closure afecta otras final int nolocal = 3;
global++; return x -> {
partes del programa
}; int local=4;
return func; (por la modificación at1++;
} de global y de ac1) ac1++;
int main() { nolocal++;
int localmain = 4; ¿Estos lenguajes return local+x;
auto cl1= f(); tienen sensibilidad a la };
cl1(); }
cl1(); historia? }
printf(global); No, el lenguaje
}
prohíbe modificar las error: local variables referenced from a
variables capturadas lambda expression must be final or
por copia effectively final: nolocal++;
Resolución parcial de Ejercicio 12, TP 06
● Variables estáticas en direcciones entre $10 y $90
1 int w = 1 18 func main() {
● Registros de activación en direcciones a partir de $100
2 func f1() { 19 int y=0
● Enteros ocupan 4 bytes
3 int x = 2 20 c1 = f1()
● El lenguaje no almacena las direcciones del código ejecutable de la unidad del
4 return () { 21 c1()
closure (llamada estática).
5 int z = x 22 c1()
● Los registros de activación de cada unidad se inician en múltiplos de 100.
6 print w+x+z 23 c2 = f1()
7 print &w, &x, &z 24 c2()
8 w++ 25 f2(c2) Realizar los diagramas de las pilas de
9 x++ 26 print &y, &c1 ejecución para los momentos donde se
Salidas:
10 z++ 27 }
terminan de ejecutar cada una de las 5
11 }
12 } siguientes líneas de código: $10, $104, $200
■ 20 8
13 func f2(func c) { ■ 7 (durante la llamada en 21) $10, $104, $200
14 int s = 1 ■ 10 (durante la llamada en 21)
15 print &s 7
■ 7 (durante la llamada en 22)
16 c()
■ 10 (durante la llamada en 22)
$10, $108, $200
17 }
■ 23 $200
■ 7 (durante la llamada en 24) 10
■ 10 (durante la llamada en 24) $10, $108, $300
■ 7 (durante la llamada en 16) $100, $104, $108
■ 10 (durante la llamada en 16).
Resolución parcial de Ejercicio 12, TP 06
1 int w = 1 18 func main() {
c1
2 func f1() { 19 int y=0 f x, $200, 2 z, $200, 2 z, $200, 3
3 int x = 2 20 c1 = f1()
4 return () { 21 c1()
y, $100, 0 y, $100, 0 y, $100, 0
5 int z = x 22 c1()
main c1, $ 104, 2 c1, $104, 2 c1, $104, 3
6 print w+x+z 23 c2 = f1()
c2, $ 108, c2, $ 108, c2, $ 108,
7 print &w, &x, &z 24 c2()
8 w++ 25 f2(c2)
9 x++ 26 print &y, &c1 Est. w, $10, 1 w, $10, 1 w, $10, 2
10 z++ 27 }
11 } 20: c1 = f() 7: 1ra llamada a c1() 10: antes de terminar c1()
12 }
Salidas:
c1
13 func f2(func c) { 5 z, $200, 3 z, $200, 4
14 int s = 1 $10, $104, $200
15 print &s
¿Por qué se
8
16 c() $10, $104, $200 produce y, $100, 0 y, $100, 0
main c1, $104, 3 c1, $104, 4
17 } 7 este valor c2, $108, c2, $108,
$10, $108, $200 3?
$200
Est. w, $10, 2 w, $10, 3
10
$10, $108, $300 7: 2da llamada a c1() 10: antes de terminar c1()
$100, $104, $108

También podría gustarte