• Publicidad

Sintaxis avanzada

Así que programas sin strict y las expresiones regulares son otro modo de hablar. Aquí encontrarás respuestas de nivel avanzado, no recomendable para los débiles de corazón.

Sintaxis avanzada

Notapor Javier » 2016-03-13 11:00 @500

Buenas tardes.

He estado intentando documentar el modo más eficiente para pasar una URI /tema1/tema2/tema3 a un hash que anide jerárquicamente cada una de las partes de la dirección: %dir = (tema1=>{tema2=>{tema3}}).

He encontrado un código en un foro que no consigo comprender, bien por la notación o por que hay una función asociativa que desconozco.

Sintáxis: [ Descargar ] [ Ocultar ]
Using perl Syntax Highlighting
  1. my $tree = {};
  2. foreach my $input (<DATA>) {
  3.     chomp $input;
  4.     my $t = $tree;
  5.  
  6.     $t = $t->{$_} //= {} for split /\// => $input;
  7. }
  8. __DATA__
  9. tema1/tema2/tema3
Coloreado en 0.005 segundos, usando GeSHi 1.0.8.4


Me gustaría entender qué significa $tree = {}. ¿un hash anónimo? Por otro lado, la línea que acumula la jerarquía me resulta poco clara. ¿Qué es //=? ¿Una función?

Gracias por vuestro conocimiento.
Javier
Perlero nuevo
Perlero nuevo
 
Mensajes: 9
Registrado: 2014-08-31 03:24 @183

Publicidad

Re: Sintaxis avanzada

Notapor explorer » 2016-03-13 13:25 @600

Hola, Javier.

La sentencia my $tree = {}; se refiere a que la variable escalar $tree contendrá una referencia a un hash anónimo.

Las referencias son como los punteros de otros lenguajes: permiten acceder a otra información referenciada por el contenido. Más información en tu propio ordenador en perldoc perlref, y en la Web (traducido al español).

Lo que está haciendo el programador es crear el nodo raíz de un árbol.

Luego, procesa cada línea de la sección __DATA__.

Por cada línea, inicializa una referencia ($t) al nodo raíz ($tree). Es de donde siempre partimos para crear las ramas.

Luego, hace un bucle for por cada elemento de $input extraído de los delimitadores '/'.

Por cada elemento, se ejecuta el operador lógico '//', que es el defined-or (más información en perldoc perlop, sección Logical Defined-Or).

El operador '//' devuelve la expresión de la izquierda si está definida, y si no, devuelve la expresión de la derecha. Es decir, que

"EXPR1 // EXPR2" es casi lo mismo que escribir "defined(EXPR1) ? EXPR1 : EXPR2". O sea, se comprueba la "definición" de las expresiones, no su "veracidad".

En este caso la expresión de la izquierda es "$t->{$_}", mientras que la expresión de la derecha es "{}".

La forma '//=' es la forma acortada de escribir

$t->{$_} = $t->{$_} // {}

Entonces, lo que hace esa operación es, primero, preguntarse si está definida la expresión "$t->{$_}".

Si lo está, entonces, asigna el valor de "$t->{$_}" a sí mismo, y si no, le asigna el valor de '{}' (una referencia a otro hash anónimo). Esto tiene el efecto de que estamos preguntando si existe (está definida) la rama correspondiente al nodo $_ (el elemento de la ruta que estamos analizando). Si existe, no hacemos nada (lo dejamos como está), pero si no existe, creamos una nueva rama para ese nodo, y que además apunte a un hash vacío.

Para el caso del ejemplo. "tema1" es el primer elemento. Partiendo de que %$tree no contiene ningún elemento, al llegar a ese línea, nos preguntamos si está definida la expresión $t->{'tema1'}. Obviamente, no lo está, así que la expresión termina siendo $t->{'tema1'} = {}, con lo que estamos creando una rama nueva al árbol, llamada 'tema1', y que tiene una hoja vacía.

Pero todavía no ha terminado la línea 6. Queda la asignación "$t = ... lo anterior ...;". Lo que estamos haciendo es que $t "se mueve" por la nueva rama que acabamos de crear (o una rama existente, en caso de que hubiera existido antes). De esta manera, estamos profundizando en la rama, recorriendo los nodos según la ruta indicada por $input. Y creando nodos vacíos en los extremos.

En la siguiente vuelta del bucle for, preguntamos si está definida la expresión $t->{'tema2'}. $t apuntaba a 'tema1', así que en realidad estamos preguntando por $tree->{'tema1'}->{'tema2'}. Como es cierto que no existe, asignamos '{}' a esa expresión, con lo que queda $tree->{'tema1'}->{'tema2'} = {} (creamos un nuevo nodo 'tema2' y que además apunta a nodo vacío).

Y así para 'tema3'.

El resultado es la creación de un árbol como este:
Sintáxis: [ Descargar ] [ Ocultar ]
Using text Syntax Highlighting
$tree = {
          'tema1' => {
                       'tema2' => {
                                    'tema3' => {}
                                  }
                     }
        };
Coloreado en 0.000 segundos, usando GeSHi 1.0.8.4

Tienes más diversión sobre referencias y estructuras complejas en perldoc perlreftut, y en la Web (traducido al español).
JF^D Perl programming & Raku programming. Grupo en Telegram: https://t.me/Perl_ES
Avatar de Usuario
explorer
Administrador
Administrador
 
Mensajes: 14476
Registrado: 2005-07-24 18:12 @800
Ubicación: Valladolid, España

Re: Sintaxis avanzada

Notapor Javier » 2016-03-14 04:00 @208

Gracias, explorer.

Ahora lo entiendo. Nunca había manejado //= y tampoco sabía dónde buscar documentación sobre él.

Saludos.
Javier
Perlero nuevo
Perlero nuevo
 
Mensajes: 9
Registrado: 2014-08-31 03:24 @183


Volver a Avanzado

¿Quién está conectado?

Usuarios navegando por este Foro: No hay usuarios registrados visitando el Foro y 1 invitado

cron