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:
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).