• Publicidad

Variables estáticas en Perl

¿Apenas comienzas con Perl? En este foro podrás encontrar y hacer preguntas básicas de Perl con respuestas aptas a tu nivel.

Variables estáticas en Perl

Notapor fgalves » 2007-08-14 09:20 @431

Hola a todos,

Me sería muy útil declarar una variable estática (algo parecido al "static" de C) en una función Perl, de manera que conservara el valor de la última ejecución en vez de reiniciarla a cero. De hecho, se trata de un contador.

¿Existe algo similar al "static" de C en Perl?

¡Muchas gracias!!
Felipe
fgalves
Perlero nuevo
Perlero nuevo
 
Mensajes: 210
Registrado: 2006-09-25 13:54 @621

Publicidad

Notapor explorer » 2007-08-14 10:01 @459

Esa pregunta está respondida en el perlfaq7, How do I create a static variable? y en perlsub, Persistent Private Variables.

Básicamente, se trata de usar una variable léxica fuera de su ámbito de declaración, de forma que solo sea conocida en las funciones definidas en aquel ámbito.

Mientras que la solución más sencilla es definir una variable léxica fuera de la función:
Sintáxis: [ Descargar ] [ Ocultar ]
Using perl Syntax Highlighting
my $contador;

sub incrementar {
    $contador++;
}
Coloreado en 0.003 segundos, usando GeSHi 1.0.8.4
el problema es que se está compartiendo la variable $contador entre todas aquellas llamadas a la función incrementar() y la variable $contador es accesible por cualquiera.

De la forma indicada,
Sintáxis: [ Descargar ] [ Ocultar ]
Using perl Syntax Highlighting
{
    my $contador;

    sub incrementar {
        $contador++;
    }
}
Coloreado en 0.001 segundos, usando GeSHi 1.0.8.4
hay un contexto en el cual está tanto la variable como la función que la incrementa. Cuando el contexto termina, no tenemos 'ninguna' forma de acceder a la variable (está fuera de su contexto), pero si llamamos a la función, seguirá incrementándose.

(Seguramente los más expertos del lugar tendrán otras explicaciones).

Otra opción es usar Perl6, que sí incorpora un modo estático para las variables, con el identificador 'state' (How will you use state declared variables in Perl6?)
JF^D Perl programming & Raku programming. Grupo en Telegram: https://t.me/Perl_ES
Avatar de Usuario
explorer
Administrador
Administrador
 
Mensajes: 14480
Registrado: 2005-07-24 18:12 @800
Ubicación: Valladolid, España

Notapor Perl user » 2007-08-14 11:14 @510

Qué tal,

Pues la respuesta practicamente ya te la dió explorer, solo vengo a aclarar algunos puntos importantes.

"static" como lo mencionas, tiene a su vez dos contextos: para variables, y para funciones. Para funciones basta decir que simplemente inhibe el uso de funciones fuera del marco del archivo actual (.c). Para variables tiene dos diferentes usos: Si una variable global es declarada utilizando el calificador static, de la misma manera el símbolo no podrá ser accedido desde otro lugar que no sea dentro del mismo archivo fuente, por otro lado, si una variable local (a una función o bloque) es declarada static, dicha variable mantendrá su estado con las llamadas subsecuentes de la función.

En Perl, la manera más sencilla de lograr dicho comportamiento (y claro, que con muchas ventajas más), es utilizando un "closure". Gracias a que Perl tiene como característica el uso de variables léxicas, estás son creadas en tiempo de compilación con cualidades especiales (REFCNT) que hace que se comporten de manera específica ante ciertos casos, como lo es con un closure (que son llamados "lexical closures", por cierto). Un closure no es mas que una función qué tiene adjuntada una o mas variables (o funciones) que mantienen un estado específico, dentro de un ambiente de ejecución y un alcance.

Sintáxis: [ Descargar ] [ Ocultar ]
Using perl Syntax Highlighting
{
    my $foo = 1;
    sub count { ++$foo }
}

# o incluso
sub make_count {
    my $foo = 1;
    return sub { ++$foo };
}

count(); # 2
count(); # 3

my $cnt = make_count();
$cnt->(); # 2
$cnt->(); # 3
 
Coloreado en 0.001 segundos, usando GeSHi 1.0.8.4


Ambos ejemplos anteriores usan un closure para generar un pequeño contador que mantiene su estado con cada llamada. Las ventajas son muchas, y son también muchas las cosas que puedes hacer con un closure.

Otra manera, un poco _más_ avanzada de hacer lo que necesitas es utilizando el módulo Lexical::Persistence, que te permite definir contextos en los que una función podrá ser ejecutada, y mantener el estado de ciertas variables. Utiliza internamente "magia" por medio de los módulos Data::LexAlias y PadWalker; módulos que permiten crear un alias (como referencias en C++, en este contexto) mientras que el segundo permite la inspección de valores léxicos (pads) de una función.

Ya tienes dos opciones, y seguramente podría haber alguna otra...

Saludos,
Marco A. Manzo
[email protected]
http://www.unixmonkeys.com/amnesiac/
Perl Programming Language
Perl user
Maestro honorario
Maestro honorario
 
Mensajes: 271
Registrado: 2004-11-03 21:11 @924


Volver a Básico

¿Quién está conectado?

Usuarios navegando por este Foro: No hay usuarios registrados visitando el Foro y 0 invitados