• Publicidad

Duda con estructura en WWW::Mechanize

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

Duda con estructura en WWW::Mechanize

Notapor StickyBit » 2011-12-07 08:25 @392

¡¡¡Hola!!!

Recién estoy aprendiendo Perl. He tenido que usar WWW::Mechanize para automatizar unos procesos web, y funciona, pero no tengo claro cómo está funcionando una parte del código que busqué de ejemplo en CPAN.

Es esta parte:
Sintáxis: [ Descargar ] [ Ocultar ]
Using perl Syntax Highlighting
  1. $m->get( $url );
  2.         my @links= @{$m->links};
  3.         foreach my $link (0..$#links) {
  4.                 next if $links[$link][0] !~ /\.shtml$/i;
  5.                 push(@lista,$links[$link][0]);
  6.         }
  7.         return @lista;
  8. }
Coloreado en 0.003 segundos, usando GeSHi 1.0.8.4


No entiendo la estructura de datos que se está utilizando...
Sintáxis: [ Descargar ] [ Ocultar ]
Using perl Syntax Highlighting
 my @links= @{$m->links};
Coloreado en 0.001 segundos, usando GeSHi 1.0.8.4


Hasta donde entiendo, $m contendrá una referencia a los datos devueltos por ->links, pero a $m lo estamos casteando como la referencia de un array, para guardarlo en el array @links.

Y después de eso,
Sintáxis: [ Descargar ] [ Ocultar ]
Using perl Syntax Highlighting
  1. next if $links[$link][0]
Coloreado en 0.001 segundos, usando GeSHi 1.0.8.4

se está accediendo a los datos como... ¿un array bidimensional?

Si miro el source de WWW::Mechanize, la sub links() devuelve un hash:

Sintáxis: [ Descargar ] [ Ocultar ]
Using perl Syntax Highlighting
  1. return @{$self->{links}} if wantarray;
  2. return $self->{links};
Coloreado en 0.001 segundos, usando GeSHi 1.0.8.4

O sea, si se castea a un hash así @{}, ¿se obtiene un array bidimensional con key y value? ¡Qué mareo! :?

Gracias , ¡salu2!
StickyBit
Perlero nuevo
Perlero nuevo
 
Mensajes: 3
Registrado: 2011-12-07 08:10 @382

Publicidad

Re: Duda con estructura en WWW::Mechanize

Notapor explorer » 2011-12-07 10:40 @486

Bienvenido a los foros de Perl en español, StickyBit.

StickyBit escribiste:No entiendo la estructura de datos que se está utilizando...
Sintáxis: [ Descargar ] [ Ocultar ]
Using perl Syntax Highlighting
 my @links= @{$m->links};
Coloreado en 0.001 segundos, usando GeSHi 1.0.8.4
Hasta donde entiendo, $m contendrá una referencia a los datos devueltos por ->links, pero a $m lo estamos casteando como la referencia de un array, para guardarlo en el array @links.
No... $m es el objeto WWW::Mechanize. Con $m->links estamos ejecutando el método links() sobre ese objeto. El resultado de la llamada es una referencia a un array. Con el 'cast' lo que realmente estamos haciendo es des-referenciar esa referencia, con lo que obtenemos la lista de valores (del array referenciado). Finalmente, esa lista de valores es almacenada en el array @links.

Viendo la documentación de links() en WWW::Mechanize, se dice que devuelve, en contexto lista, una lista de objetos WWW::Mechanize::Link, así que es normal que una lista se guarde en un array. Si la evaluamos en contexto escalar devuelve un referencia a esa lista.

En Perl, no se hace 'casting', sino que se referencia o se desreferencia. Un caso especial es cuando se extraen las claves/valores de un hash y se meten en un array, pero aún así no hay cambios de tipos.

De todas maneras... el 'cast' me sobra... Perl ya sabe que se está ejecutando en contexto lista, ya que es una asignación a un array. La línea la escribiría así:
Sintáxis: [ Descargar ] [ Ocultar ]
Using perl Syntax Highlighting
  1.         my @links= $m->links;
Coloreado en 0.001 segundos, usando GeSHi 1.0.8.4


StickyBit escribiste:Y después de eso,
Sintáxis: [ Descargar ] [ Ocultar ]
Using perl Syntax Highlighting
next if $links[$link][0]
Coloreado en 0.001 segundos, usando GeSHi 1.0.8.4

se está accediendo a los datos como... ¿un array bidimensional?
@links es un array, así que $links[$link] es un elemento, el $link-ésimo dentro de ese array ($link es el índice). Ese elemento es un objeto WWW::Mechanize::Link que, si miramos su código fuente, se trata de un array.

El autor del código que publicas, ha decidido que prefiere acceder al contenido del objeto WWW::Mechanize::Link de forma directa, por lo que ha escrito esto:
Sintáxis: [ Descargar ] [ Ocultar ]
Using perl Syntax Highlighting
next if $links[$link]->[0]
Coloreado en 0.001 segundos, usando GeSHi 1.0.8.4
para acceder al primer elemento del array del objeto.

Como en Perl se puede abreviar el operador '->' cuando está entre corchetes y llaves, pues lo ha quitado.

El caso es que esto es justo lo que no hay que hacer: no hay que acceder a los datos internos de un objeto de forma directa. Lo mejor es usar las funciones de acceso a esos datos. Lo que el autor debía haber escrito es esto:
Sintáxis: [ Descargar ] [ Ocultar ]
Using perl Syntax Highlighting
next if $links[$link]->url
Coloreado en 0.001 segundos, usando GeSHi 1.0.8.4
estaría ejecutando el método url() sobre el objeto. Incluso queda más claro: estamos obteniendo la parte URL del objeto WWW::Mechanize::Link.

StickyBit escribiste:Si miro el source de WWW::Mechanize, la sub links() devuelve un hash:
Sintáxis: [ Descargar ] [ Ocultar ]
Using perl Syntax Highlighting
  1. return @{$self->{links}} if wantarray;
  2. return $self->{links};
Coloreado en 0.001 segundos, usando GeSHi 1.0.8.4

O sea, si se castea a un hash así @{}, ¿se obtiene un array bidimensional con key y value? ¡Qué mareo! :?
No... hay que prestar atención a los detalles...
  • $self es el objeto WWW::Mechanize. Este objeto guarda su información en un hash
  • $self->{links} es una de las claves, donde guarda la información de los enlaces encontrados en la página. Lo que guarda es una referencia a un array con objetos WWW::Mechanize::Link (mira el código de sub _extract_links())
  • dentro de links(), como indicas, se mira a ver si el programador desea obtener una lista de valores (contexto lista) o no (contexto escalar, solo un valor)
  • si quiere una lista, extrae la referencia ($self->{links}) y la desreferencia (@{}), extrayendo todos los valores, y sacándolos por el return (o sea, que devuelve una lista de valores)
  • si no, devuelve la referencia tal cual (solo un valor).
JF^D Perl programming & Raku programming. Grupo en Telegram: https://t.me/Perl_ES
Avatar de Usuario
explorer
Administrador
Administrador
 
Mensajes: 14486
Registrado: 2005-07-24 18:12 @800
Ubicación: Valladolid, España


Volver a Básico

¿Quién está conectado?

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

cron