<?xml version='1.0' encoding='UTF-8'?><?xml-stylesheet href="http://www.blogger.com/styles/atom.css" type="text/css"?><feed xmlns='http://www.w3.org/2005/Atom' xmlns:openSearch='http://a9.com/-/spec/opensearchrss/1.0/' xmlns:georss='http://www.georss.org/georss' xmlns:gd='http://schemas.google.com/g/2005' xmlns:thr='http://purl.org/syndication/thread/1.0'><id>tag:blogger.com,1999:blog-5238463735728501931</id><updated>2011-10-10T10:18:55.278-04:30</updated><category term='Python'/><category term='PostgreSQL'/><category term='Noticias'/><category term='Programación Funcional'/><category term='Plack'/><category term='Patentes'/><category term='Programación'/><category term='Seguridad'/><category term='Mitos'/><category term='Perl'/><category term='Tutorial'/><category term='Comunidad'/><category term='Java'/><category term='Licencias'/><category term='Lenguajes'/><category term='CPAN'/><category term='Moose'/><category term='Web'/><category term='Estilo'/><title type='text'>Perliscopio</title><subtitle type='html'>Cualquier cosa sobre Perl</subtitle><link rel='http://schemas.google.com/g/2005#feed' type='application/atom+xml' href='http://perliscopio.blogspot.com/feeds/posts/default'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5238463735728501931/posts/default?max-results=100'/><link rel='alternate' type='text/html' href='http://perliscopio.blogspot.com/'/><link rel='hub' href='http://pubsubhubbub.appspot.com/'/><author><name>Jose Rey</name><uri>http://www.blogger.com/profile/15071755167581242815</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><generator version='7.00' uri='http://www.blogger.com'>Blogger</generator><openSearch:totalResults>30</openSearch:totalResults><openSearch:startIndex>1</openSearch:startIndex><openSearch:itemsPerPage>100</openSearch:itemsPerPage><entry><id>tag:blogger.com,1999:blog-5238463735728501931.post-5662072004288664720</id><published>2011-04-22T00:35:00.003-04:30</published><updated>2011-04-22T08:14:29.828-04:30</updated><category scheme='http://www.blogger.com/atom/ns#' term='Perl'/><title type='text'>Ya viene Perl 5.14</title><content type='html'>[&lt;a href="http://translate.google.com/translate?js=n&amp;amp;prev=_t&amp;amp;hl=es&amp;amp;ie=UTF-8&amp;amp;layout=2&amp;amp;eotf=1&amp;amp;sl=es&amp;amp;tl=en&amp;amp;u=http%3A%2F%2Fperliscopio.blogspot.com%2F2011%2F04%2Fya-viene-perl-514.html"&gt;English translation by google&lt;/a&gt;]&lt;br /&gt;&lt;br /&gt;Hace unas horas &lt;a href="http://search.cpan.org/dist/perl-5.14.0-RC1/"&gt;salió el primer candidato a lo que será Perl 5.14&lt;/a&gt; (ahora tenemos nuevas versiones de perl a cada rato :) en esta versión vienen nuevas características convenientes y algunas optimizaciones (sobre todo en windows).&lt;br /&gt;&lt;h2&gt;Simetría entre arreglos, hashes y sus referencias&lt;/h2&gt;Esta es una de las características que más me gustan de Perl 5.14, pues simplifica la sintaxis cuando se manipulan referencias.&lt;br /&gt;&lt;br /&gt;En el caso de los arreglos las primitivas como &lt;code&gt;push&lt;/code&gt;, &lt;code&gt;shift&lt;/code&gt;, &lt;code&gt;unshift&lt;/code&gt;, &lt;code&gt;pop&lt;/code&gt; y &lt;code&gt;slice&lt;/code&gt; ahora aceptan referencias permitiendo cambiar el código:&lt;br /&gt;&lt;pre&gt;&lt;code&gt;&lt;br /&gt;  push @{ $arr-&amp;gt;[1] }, 8&lt;br /&gt;  $head = shift @{ $obj-&amp;gt;arrayref }&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;por versiones más sencillas que ya no necesitan la dereferencia: &lt;br /&gt;&lt;pre&gt;&lt;code&gt;&lt;br /&gt;  push $arr-&amp;gt;[1], 8&lt;br /&gt;  $head = shift $obj-&amp;gt;arrayref&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;lo que sin duda se ve mejor, sobre todo para los novatos.&lt;br /&gt;&lt;br /&gt;Adicionalmnete &lt;code&gt;keys&lt;/code&gt;, &lt;code&gt;values&lt;/code&gt; y &lt;code&gt;each&lt;/code&gt; trabajan con referecias a hashes, pero también trabajarán con arreglos y sus referecias, en este último caso se asumirán los valores del arreglo y las claves seran los índices enteros, así que se podrán hacer cosas como:&lt;br /&gt;&lt;pre&gt;&lt;code&gt;&lt;br /&gt;  for ( values $obj-&amp;gt;arrayref ) { ... }&lt;br /&gt;  for ( keys $obj-&amp;gt;arrayref ) { ... }&lt;br /&gt;  for ( keys %{$hoh-&amp;gt;{genres}{artists}} ) {...}&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;En vez de:&lt;br /&gt;&lt;pre&gt;&lt;code&gt;&lt;br /&gt;  for ( @{ $obj-&amp;gt;arrayref } ) { ... }&lt;br /&gt;  for ( 0 .. @{ $obj-&amp;gt;arrayref } ) { ... }&lt;br /&gt;  for ( keys $hoh-&amp;gt;{genres}{artists}    ) {...}&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;simplificando igualmente la sintaxis.&lt;br /&gt;&amp;nbsp; &lt;br /&gt;Una tabla de la documentación da varios ejemplos adicionales:&lt;br /&gt;&lt;pre&gt;&lt;code&gt;&lt;br /&gt;  |----------------------------+---------------------------|&lt;br /&gt;  | Sintaxis tradicional       | Sintaxis compacta         |&lt;br /&gt;  |----------------------------+---------------------------|&lt;br /&gt;  | push @$arrayref, @stuff    | push $arrayref, @stuff    |&lt;br /&gt;  | unshift @$arrayref, @stuff | unshift $arrayref, @stuff |&lt;br /&gt;  | pop @$arrayref             | pop $arrayref             |&lt;br /&gt;  | shift @$arrayref           | shift $arrayref           |&lt;br /&gt;  | splice @$arrayref, 0, 2    | splice $arrayref, 0, 2    |&lt;br /&gt;  | keys %$hashref             | keys $hashref             |&lt;br /&gt;  | keys @$arrayref            | keys $arrayref            |&lt;br /&gt;  | values %$hashref           | values $hashref           |&lt;br /&gt;  | values @$arrayref          | values $arrayref          |&lt;br /&gt;  | ($k,$v) = each %$hashref   | ($k,$v) = each $hashref   |&lt;br /&gt;  | ($k,$v) = each @$arrayref  | ($k,$v) = each $arrayref  |&lt;br /&gt;  |----------------------------+---------------------------|&lt;/code&gt;&lt;/pre&gt;&lt;h2&gt;Paquetes con bloques&lt;/h2&gt;Generalmente cuando se hace un script rápidamente, es más fácil declarar los paquetes (clases) en el mismo archivo, de igual manera es fácil caer en alguna trampa debido a que se tienen varios paquetes en un mismo entorno léxico, así cuando se declaran pragmas o variables léxicas, estas terminan afectando a otras clases o paquetes porque las declaraciones tienen como alcance léxico a todo el archivo, la manera estándar de evitar esto es declarando cada clase dentro de un bloque que acota su alcance léxico:&lt;br /&gt;&lt;pre&gt;&lt;code&gt;&lt;br /&gt;  {&lt;br /&gt;    package Uno;&lt;br /&gt;    ...&lt;br /&gt;  }&lt;br /&gt;  {&lt;br /&gt;    package Dos;&lt;br /&gt;    ...&lt;br /&gt;  }&lt;br /&gt;  ...&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;En perl 5.14 un paquete puede tener un bloque, haciendo que la construcción anterior se vea mejor:&lt;br /&gt;&lt;pre&gt;&lt;code&gt;&lt;br /&gt;  package Uno {&lt;br /&gt;    ...&lt;br /&gt;  }&lt;br /&gt;  package Dos {&lt;br /&gt;    ...&lt;br /&gt;  }&lt;br /&gt;  ...&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;h2&gt;Substitución no destructiva&lt;/h2&gt;Se implementa utilizando el modificador /r a una substitución, logrando que la variable ligada a la operación no sea afectada por la misma, en su lugar se retornará el valor modificado, así que el siguiente código:&lt;br /&gt;&lt;pre&gt;&lt;code&gt;&lt;br /&gt;  $result = do {&lt;br /&gt;    my $ret = $text;&lt;br /&gt;    $ret =~ s/pedro/juan/;&lt;br /&gt;    $ret;&lt;br /&gt;  };&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;Se podrá escribir de manera mas concisa en 5.14:&lt;br /&gt;&lt;pre&gt;&lt;code&gt;&lt;br /&gt;  $result = $text =~ s/pedro/juan/r&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;Este modificador también se agregó a la transliteración: &lt;code&gt;tr///r&lt;/code&gt;&lt;br /&gt;&lt;h2&gt;given devuelve valores&lt;/h2&gt;Siendo un fanático de Lisp esta característica me gustó, pues con frecuencia suelo simular &lt;code&gt;(cond ...)&lt;/code&gt; en Perl haciendo:&lt;br /&gt;&lt;pre&gt;&lt;code&gt;&lt;br /&gt;my $result;&lt;br /&gt;given ($val) {&lt;br /&gt;    when(1) { $result = "uno" }&lt;br /&gt;    when(2) { $result = "dos" }&lt;br /&gt;    default { $result = undef }&lt;br /&gt;}&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;En Perl 5.14 se podrá retornar un valor directamente, encapsulando toda la logica y sin necesidad de utilizar variables auxiliares fuera de la estructura:&lt;br /&gt;&lt;pre&gt;&lt;code&gt;&lt;br /&gt;my $result = do {&lt;br /&gt;  given ($val) {&lt;br /&gt;    when(1) { "uno" }&lt;br /&gt;    when(2) { "dos" }&lt;br /&gt;    default { undef }&lt;br /&gt;} };&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;El do todavía es necesario ya que el parser de Perl todavía no reconoce la instrucción given como una expresión, aunque probablemente lo haga en el futuro.&lt;br /&gt;&lt;h2&gt;\o{...} para incluir caracteres en código octal&lt;/h2&gt;Desde siempre Perl permite especificar caracteres como "\0376" sin embargo esta secuencia solo se permite para caracteres hasta 0777 (511), con la nueva secuencia se pueden especificar caracteres unicode con códigos mucho mayores, además el uso de esta secuencia permite eliminar confusiones con las retro-referencias (backreferences) en las expresiones regulares.&lt;br /&gt;&lt;h2&gt;Mejoras en Unicode&lt;/h2&gt;Ahora se reconocen todo los nombres del unicode incluyendo abreviaturas y nombres de los caracteres de control, así que se pueden escribir caracteres como: "\N{ACK}", "\N{NBSP}", "\N{BEL}", entre otros. Estos nombres también se reconocen tanto en \N{} como en &lt;a href="http://search.cpan.org/%7Ejesse/perl-5.14.0-RC1/lib/charnames.pm"&gt;charnames&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;Se introduce el pragma:&amp;nbsp; &lt;code&gt;use feature "unicode_strings"&lt;/code&gt; que permite resolver la mayoría de las inconsistencias en la búsqueda de expresiones regulares con unicode, este pragma permitirá que el resultado funcione igual sin importar si la cadena es utf8 o no.&lt;br /&gt;&lt;br /&gt;Se introducen los modificadores &lt;code&gt;/d&lt;/code&gt;, &lt;code&gt;/l&lt;/code&gt; y &lt;code&gt;/u&lt;/code&gt; en las expresiones regulares:&lt;br /&gt;&lt;ul&gt;&lt;li&gt;&lt;code&gt;/l&lt;/code&gt; para compilar la expresión regular como si estuviera en el contexto del pragma: &lt;code&gt;use locale&lt;/code&gt;&lt;/li&gt;&lt;li&gt;&lt;code&gt;/u&lt;/code&gt; para compilar la expresión regular como si estuviera en el contexto del pragma: &lt;code&gt;use feature "unicode_strings" &lt;/code&gt;&lt;/li&gt;&lt;li&gt;&lt;code&gt;/d&lt;/code&gt; permite anular los efectos de los pragmas: &lt;code&gt;use locale&lt;/code&gt; y &lt;code&gt;use feature "unicode_strings" &lt;/code&gt;&lt;/li&gt;&lt;li&gt;&lt;code&gt;/a&lt;/code&gt; para interpretar la expresión como si fuera ASCII así &lt;code&gt;\s&lt;/code&gt; encontrará exactamente los caracteres &lt;code&gt;[ \f\n\r\t]&lt;/code&gt;, &lt;code&gt;\d&lt;/code&gt; encontrará exactamente &lt;code&gt;[0123456789]&lt;/code&gt;, &lt;code&gt;\w&lt;/code&gt; encontrá exactamente los 63 caracteres &lt;code&gt;[A-Za-z0-9_]&lt;/code&gt;, y las clases de caracteres &lt;code&gt;[[:posix:]]&lt;/code&gt; solamente conseguiran los caracteres apropiados del ASCII, también se afectan apropiadamente: &lt;code&gt;\b&lt;/code&gt; y &lt;code&gt;\B&lt;/code&gt;. Los complementos de estas clases consiguen cualquier cosa fuera de esto, como se debe.&lt;/li&gt;&lt;/ul&gt;&lt;h2&gt;Filehandle cargará automáticamente IO::File&lt;/h2&gt;Ahora cualquier filehandle se comportará como un IO::File, cuando se invoque un método inexistente para un filehandle perl cargará automáticamente IO::File, y reintentará la invocación nuevamente.&lt;br /&gt;&lt;h2&gt;Mejoras en las funciones tipo printf&lt;/h2&gt;Ahora todas las funciones de la familia printf entienden los modificadores del estándar C90: "hh" (char), "z" (size_t), and "t" (ptrdiff_t), si además perl se compila con un compilador C99 también se interpretará el modificador "j" (intmax_t).&lt;br /&gt;&lt;h2&gt;Introspección sobre el proceso de compilación&lt;/h2&gt;La nueva variable global &lt;code&gt;${^GLOBAL_PHASE}&lt;/code&gt; permitirá a los programas hacer introspección sobre la fase de compilación que se lleva a cabo, lo que permitirá en el futuro mejorar las capacidades de autoextensión del lenguaje.&lt;br /&gt;&lt;br /&gt;Para aquellos que no esten al tanto de las capacidades de Perl, enterense que los programas en Perl pueden ejecutarse en tiempo de compilación para alterar el mismo proceso de compilación del programa, por eso aparecen características como está, que facilitará el desarrollo de nuevas extensiones al lenguaje.&lt;br /&gt;&lt;h2&gt;Inyección de operaciones en la máquina virtual&lt;/h2&gt;Ahora se pueden registrar nuevas operaciones en la máquina virtual de perl, esto facilitará en el futuro la extensión de la máquina virtual con nuevas propiedades y operaciones.&lt;br /&gt;&lt;h2&gt;Otras mejoras&lt;/h2&gt;Se optimizó la concatenación de cadenas de caracteres que pueden llegar a ser hasta 100 veces más rápidas en ciertas plataformas (como windows).&lt;br /&gt;&lt;br /&gt;Se optimizó el uso de %+ y %- para programas que no los utilizan.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5238463735728501931-5662072004288664720?l=perliscopio.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://perliscopio.blogspot.com/feeds/5662072004288664720/comments/default' title='Enviar comentarios'/><link rel='replies' type='text/html' href='http://perliscopio.blogspot.com/2011/04/ya-viene-perl-514.html#comment-form' title='2 comentarios'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5238463735728501931/posts/default/5662072004288664720'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5238463735728501931/posts/default/5662072004288664720'/><link rel='alternate' type='text/html' href='http://perliscopio.blogspot.com/2011/04/ya-viene-perl-514.html' title='Ya viene Perl 5.14'/><author><name>Jose Rey</name><uri>http://www.blogger.com/profile/15071755167581242815</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5238463735728501931.post-3914728962140035107</id><published>2010-10-08T20:20:00.000-04:30</published><updated>2010-10-08T20:20:00.662-04:30</updated><category scheme='http://www.blogger.com/atom/ns#' term='Perl'/><category scheme='http://www.blogger.com/atom/ns#' term='CPAN'/><category scheme='http://www.blogger.com/atom/ns#' term='Moose'/><title type='text'>Moose acelerando</title><content type='html'>El &lt;a href="http://search.cpan.org/perldoc?Moose"&gt;más reciente y exitoso sistema de OOP para Perl&lt;/a&gt;, se esta haciendo cada vez más veloz.&lt;br /&gt;&lt;br /&gt;En el &lt;a href="http://blog.moose.perl.org/"&gt;blog de Moose&lt;/a&gt; podemos apreciar que se trabaja continuamente en perfilar el consumo de recursos y mejorar el rendimiento de este sistema, que en su última versión (1.15) es un poquito más lento compilando, mientras incluye más código "en linea" acelerando la ejecución de los programas.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5238463735728501931-3914728962140035107?l=perliscopio.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://perliscopio.blogspot.com/feeds/3914728962140035107/comments/default' title='Enviar comentarios'/><link rel='replies' type='text/html' href='http://perliscopio.blogspot.com/2010/10/moose-acelerando.html#comment-form' title='0 comentarios'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5238463735728501931/posts/default/3914728962140035107'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5238463735728501931/posts/default/3914728962140035107'/><link rel='alternate' type='text/html' href='http://perliscopio.blogspot.com/2010/10/moose-acelerando.html' title='Moose acelerando'/><author><name>Jose Rey</name><uri>http://www.blogger.com/profile/15071755167581242815</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5238463735728501931.post-2598381247880909576</id><published>2010-10-05T21:34:00.001-04:30</published><updated>2010-10-05T21:43:23.083-04:30</updated><category scheme='http://www.blogger.com/atom/ns#' term='Perl'/><category scheme='http://www.blogger.com/atom/ns#' term='Plack'/><category scheme='http://www.blogger.com/atom/ns#' term='CPAN'/><category scheme='http://www.blogger.com/atom/ns#' term='Programación'/><category scheme='http://www.blogger.com/atom/ns#' term='Moose'/><title type='text'>Aplicaciones no tradicionales en Perl</title><content type='html'>Acabo de ver una aplicación de esas que tal vez inicialmente no se me hubiera ocurrido hacer en Perl: "&lt;a href="http://www.lacunaexpanse.com/"&gt;The Lacuna Expanse&lt;/a&gt;", esta aplicación es un juego y es masivamente paralelo, así que yo hubiera investigado como hacerla en Erlang o Haskell, sin embargo hicieron el servidor 100% en Perl, el cliente genérico esta en Javascript y luego hay otros clientes para telefonos hechos en variedad de lenguajes.&lt;br /&gt;&lt;br /&gt;Se explota el uso de JSON RPC, y el CPAN les permitió utilizar &lt;a href="http://search.cpan.org/perldoc?Plack"&gt;Plack&lt;/a&gt;, &lt;a href="http://search.cpan.org/perldoc?Moose"&gt;Moose&lt;/a&gt;, &lt;a href="http://search.cpan.org/perldoc?DBIx::Class"&gt;DBIx::Class&lt;/a&gt; y la estrella de la fiesta: &lt;a href="http://search.cpan.org/perldoc?JSON::RPC::Dispatcher"&gt;JSON::RPC::Dispatcher&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;Si quieren más información pueden leer el artículo de &lt;a href="http://blogs.perl.org/users/ovid/2010/10/the-lacuna-expanse.html"&gt;Ovid&lt;/a&gt; y el de &lt;a href="http://blogs.perl.org/users/jt_smith/2010/10/why-the-lacuna-expanse-is-good-for-perl.html"&gt;JT Smith&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;Aquí les dejo el trailer para que alucinen.&lt;br /&gt;&lt;br /&gt;&lt;object height="390" width="640"&gt;&lt;param name="movie" value="http://www.youtube.com/v/efsJRdJ6dog&amp;hl=en_US&amp;feature=player_embedded&amp;version=3"&gt;&lt;/param&gt;&lt;param name="allowFullScreen" value="true"&gt;&lt;/param&gt;&lt;param name="allowScriptAccess" value="always"&gt;&lt;/param&gt;&lt;embed src="http://www.youtube.com/v/efsJRdJ6dog&amp;hl=en_US&amp;feature=player_embedded&amp;version=3" type="application/x-shockwave-flash" allowfullscreen="true" allowScriptAccess="always" width="640" height="390"&gt;&lt;/embed&gt;&lt;/object&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5238463735728501931-2598381247880909576?l=perliscopio.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://perliscopio.blogspot.com/feeds/2598381247880909576/comments/default' title='Enviar comentarios'/><link rel='replies' type='text/html' href='http://perliscopio.blogspot.com/2010/10/aplicaciones-no-tradicionales-en-perl.html#comment-form' title='1 comentarios'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5238463735728501931/posts/default/2598381247880909576'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5238463735728501931/posts/default/2598381247880909576'/><link rel='alternate' type='text/html' href='http://perliscopio.blogspot.com/2010/10/aplicaciones-no-tradicionales-en-perl.html' title='Aplicaciones no tradicionales en Perl'/><author><name>Jose Rey</name><uri>http://www.blogger.com/profile/15071755167581242815</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5238463735728501931.post-729915267050953141</id><published>2010-10-05T20:34:00.002-04:30</published><updated>2010-10-05T21:37:03.139-04:30</updated><category scheme='http://www.blogger.com/atom/ns#' term='Perl'/><category scheme='http://www.blogger.com/atom/ns#' term='PostgreSQL'/><category scheme='http://www.blogger.com/atom/ns#' term='Lenguajes'/><category scheme='http://www.blogger.com/atom/ns#' term='Python'/><title type='text'>Mi proveedor favorito</title><content type='html'>Hoy entrevisté a un proveedor que pudiera convertirse en uno de mis favoritos, voy a hacer una interpretación libre de la conversación y a lo mejor se imaginan porque quede gratamente impresionado:&lt;br /&gt;&lt;br /&gt;Yo: los llamé porque estoy abrumado con tantas cosas por hacer y necesito alguien que ayude a migrar bases de datos Oracle y aplicaciones de Power Builder.&lt;br /&gt;&lt;br /&gt;Proveedor: Nosotros somos especialistas en Oracle y Power Builder entre otros, pero estamos trabajando mucho con PostgreSQL, Perl, Python.&lt;br /&gt;&lt;br /&gt;Yo: Y si les pido ayuda para migrar aplicaciones Power Builder a la Web que tecnologías me recomiendan.&lt;br /&gt;&lt;br /&gt;Proveedor: Bueno nosotros trabajábamos principalmente con Python usando Django, que es un ambiente excelente, sin embargo nos hemos dado cuenta de que aunque Perl no se ve tan bonito, nos rinde más para nuestro trabajo, así que últimamente estamos trabajando más con Catalyst y Perl en general.&lt;br /&gt;&lt;br /&gt;Necesito más proveedores así, porque donde yo trabajo &lt;b&gt;si&lt;/b&gt; vamos a migrar a software libre.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5238463735728501931-729915267050953141?l=perliscopio.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://perliscopio.blogspot.com/feeds/729915267050953141/comments/default' title='Enviar comentarios'/><link rel='replies' type='text/html' href='http://perliscopio.blogspot.com/2010/10/mi-proveedor-favorito.html#comment-form' title='3 comentarios'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5238463735728501931/posts/default/729915267050953141'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5238463735728501931/posts/default/729915267050953141'/><link rel='alternate' type='text/html' href='http://perliscopio.blogspot.com/2010/10/mi-proveedor-favorito.html' title='Mi proveedor favorito'/><author><name>Jose Rey</name><uri>http://www.blogger.com/profile/15071755167581242815</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>3</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5238463735728501931.post-2308543656405524368</id><published>2010-08-15T15:27:00.001-04:30</published><updated>2010-10-05T21:38:13.785-04:30</updated><category scheme='http://www.blogger.com/atom/ns#' term='Comunidad'/><category scheme='http://www.blogger.com/atom/ns#' term='Java'/><category scheme='http://www.blogger.com/atom/ns#' term='Licencias'/><category scheme='http://www.blogger.com/atom/ns#' term='Seguridad'/><category scheme='http://www.blogger.com/atom/ns#' term='Patentes'/><title type='text'>La nueva trampa de Java</title><content type='html'>[ Este artículo es una copia del que se encuentra en &lt;a href="http://radarlibre.blogspot.com/2010/08/la-nueva-trampa-de-java.html"&gt;Radar Libre&lt;/a&gt; ]&lt;br /&gt;&lt;br /&gt;La &lt;a href="http://softlibre.barrapunto.com/article.pl?sid=10/08/13/0728242&amp;amp;from=rss"&gt;demanda iniciada por ORACLE contra Google&lt;/a&gt; donde se argumenta que el sistema operativo Android viola patentes propiedad de ORACLE, muestra una debilidad de lo que usualmente muchos en la comunidad (incluyendome) consideramos software libre.&lt;br /&gt;&lt;br /&gt;Desde que Sun Microsystems liberó la mayor parte del código de la plataforma Java, este asunto ha pasado por debajo de la mesa, pues las implementaciones que se utilizan son: la original, y alguna que otra licenciada directamente del propietario.&lt;br /&gt;&lt;br /&gt;En un debate ocurrido hace un lustro, sobre &lt;a href="http://nagui1008.blogspot.com/2005/09/resumen-de-la-semana-2.html"&gt;El uso de Java en el Plan Nacional de Migración a Software Libre&lt;/a&gt;, Simon Phipps argumentaba que Sun Microsystems era una compañía amigable, que había prometido liberar el código y que estaba trabajando para ello.&lt;br /&gt;&lt;br /&gt;En aquel momento mi argumento fue que las corporaciones no tienen alma, sentimientos o lealdad, que son básicamente actores de guerras que solo obedecen a motivos económicos y que verlas de cualquier otra manera era un riesgo que que el Estado no debería correr.&lt;br /&gt;&lt;br /&gt;Después de un lustro y luego de la desaparición Sun, al ser adquirida por ORACLE, quedó demostrado que Simon Phipps &lt;i&gt;probablemente&lt;/i&gt; tenía razón, Sun finalmente liberó &lt;i&gt;lo que pudo&lt;/i&gt; de Java y nunca aplicó tarifas al licenciamiento de la plataforma, sin embargo yo también tenía razón: las corporaciones no tienen alma y ahora que Sun fue tragada por ORACLE se lanza al ataque en contra de quien pueda rendirle beneficios.&lt;br /&gt;&lt;br /&gt;Este ataque es hoy posible gracias a un arma secreta que Sun mantenía en su arsenal: "Patentes de Software", para evitar suspicacias como las que siempre han rodeado a Mono, Sun emitió una liberación de uso de dichas patentes para cualquier implementación de&amp;nbsp; Java, siempre y cuando la implementación incluyera todas las características y servicios de la plataforma y no se incluyera ninguna característica o servicio adicional, es decir que para evitar una demanda de propiedad intelectual por patentes el distribuidor debía asegurarse de:&lt;br /&gt;&lt;br /&gt;&lt;blockquote&gt;implementar toda la plataforma y solo la plataforma&lt;/blockquote&gt;&lt;br /&gt;Aquí es donde Google cayó en la trampa porque al parecer no incluyó AWT y Swing que son parte integral de la especificación.&lt;br /&gt;&lt;br /&gt;Sin embargo lo peligroso de todo este asunto no es la demanda de ORACLE a Google, que puede presentar una buena pelea judicial al estilo SCO, Novel e IBM, sino que la trampa ahora es mucho más sutil (pero no menos potente), ya no basta que un código sea GPL versión 2 para que sea realmente libre.&lt;br /&gt;&lt;br /&gt;En los términos establecidos por la liberación de derechos de uso de las patentes de Sun se coarta la libertad 3, que da el derecho a modificar el código y redistribuir el resultado de la modificación, porque Oracle va a demandar por violación de patente al quedar fuera de la protección de la liberación de derechos de uso de patentes, independientemente de lo que diga la GPLv2.&lt;br /&gt;&lt;br /&gt;Así que en realidad aunque la mayoría del código de la plataforma Java sea libre por derecho, de hecho no es libre porque ORACLE puede utilizar otros instrumentos para ejercer coacción sobre cualquiera que intente modificar la plataforma, y por lo tanto no cumple con el espíritu del decreto 3390, por ello debe prohibirse nuevamente el uso de esta plataforma en el Estado hasta que se aclare esta situación o se libere Java bajo la licencia GPL versión 3 que incluye protección legal contra las patentes.&lt;br /&gt;&lt;br /&gt;Finalmente en un tono más personal deberíamos hacer un esfuerzo coordinado por dejar de consumir productos ORACLE para que la corporación aprenda por la única vía posible: su cuenta bancaria, que jugar con la libertad puede resultar peligroso y dañino.&lt;br /&gt;&lt;br /&gt;Dejar de consumir productos de esta infame comañía no es difícil, casi cualquier cosa que se esté haciendo con su manejador de base de datos, se puede hacer con PostgerSQL y todo el resto de sus productos son bastante malos, incluyendo el lenguaje de programación Java (no la plataforma) así que en general, dejar de usar productos ORACLE se puede considerar de entrada como una ventaja competitiva.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5238463735728501931-2308543656405524368?l=perliscopio.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://perliscopio.blogspot.com/feeds/2308543656405524368/comments/default' title='Enviar comentarios'/><link rel='replies' type='text/html' href='http://perliscopio.blogspot.com/2010/08/la-nueva-trampa-de-java.html#comment-form' title='3 comentarios'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5238463735728501931/posts/default/2308543656405524368'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5238463735728501931/posts/default/2308543656405524368'/><link rel='alternate' type='text/html' href='http://perliscopio.blogspot.com/2010/08/la-nueva-trampa-de-java.html' title='La nueva trampa de Java'/><author><name>Jose Rey</name><uri>http://www.blogger.com/profile/15071755167581242815</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>3</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5238463735728501931.post-624656787729968270</id><published>2010-03-17T21:18:00.000-04:30</published><updated>2010-03-17T21:18:46.112-04:30</updated><title type='text'>Un tutorial de catalyst en español</title><content type='html'>Como ando colapsado sin poder escribir, les dejo el &lt;a href="http://joelgomez.org.ve/?p=93"&gt;blog de un amigo&lt;/a&gt; que va a escribir una serie de artículos sobre Catalyst.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5238463735728501931-624656787729968270?l=perliscopio.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://perliscopio.blogspot.com/feeds/624656787729968270/comments/default' title='Enviar comentarios'/><link rel='replies' type='text/html' href='http://perliscopio.blogspot.com/2010/03/un-tutorial-de-catalyst-en-espanol.html#comment-form' title='0 comentarios'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5238463735728501931/posts/default/624656787729968270'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5238463735728501931/posts/default/624656787729968270'/><link rel='alternate' type='text/html' href='http://perliscopio.blogspot.com/2010/03/un-tutorial-de-catalyst-en-espanol.html' title='Un tutorial de catalyst en español'/><author><name>Jose Rey</name><uri>http://www.blogger.com/profile/15071755167581242815</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5238463735728501931.post-7281222996017752837</id><published>2010-01-31T07:26:00.004-04:30</published><updated>2010-01-31T14:41:48.450-04:30</updated><category scheme='http://www.blogger.com/atom/ns#' term='Perl'/><category scheme='http://www.blogger.com/atom/ns#' term='CPAN'/><title type='text'>Moose de dieta</title><content type='html'>[&lt;a href="http://perliscope.blogspot.com/2010/01/diet-moose.html"&gt;English translation&lt;/a&gt;]&lt;br /&gt;&lt;br /&gt;¿Te parece que &lt;a href="http://search.cpan.org/perldoc?Moose"&gt;Moose&lt;/a&gt; es demasiado pesado para tus aplicaciones?&lt;br /&gt;&lt;br /&gt;La compilación de los objetos de &lt;a href="http://search.cpan.org/perldoc?Moose"&gt;Moose&lt;/a&gt; puede tomar un tiempo considerable durante el arranque de una aplicación, esto podría dar la impresión de que los programas que utilizan &lt;a href="http://search.cpan.org/perldoc?Moose"&gt;Moose&lt;/a&gt; son lentos, sin embargo la compilación solamente ocurre al cargar el programa, y dependiendo de la aplicación pude ser que &lt;a href="http://search.cpan.org/perldoc?Moose"&gt;Moose&lt;/a&gt; no sea tan pesado como parece.&lt;br /&gt;&lt;br /&gt;Un ejemplo de ello es una aplicación en &lt;a href="http://www.catalystframework.org/"&gt;Catalyst&lt;/a&gt; (en versiones mayores a la 5.8), cuando arranca se deben compilar todos los objetos hechos en &lt;a href="http://search.cpan.org/perldoc?Moose"&gt;Moose&lt;/a&gt; y se siente la diferencia con las versiones anteriores, pero como Catalyst se va a ejecutar durante dias o meses, no importa mucho el tiempo de arranque.&lt;br /&gt;&lt;br /&gt;Si la aplicación que quieres desarrollar es un comando que ejecuta una tarea rápida y termina tal vez &lt;a href="http://search.cpan.org/perldoc?Moose"&gt;Moose&lt;/a&gt; es muy pesado para tí, sobre todo cuando ejecutas los comandos repetidamente a través de otros comandos como xargs(1) o find(1).&lt;br /&gt;&lt;br /&gt;Para los casos donde el tiempo de arranque de la aplicación no se amortiza bien con la ejecución, hay una solución en el CPAN: &lt;a href="http://search.cpan.org/perldoc?Moose"&gt;Mouse&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;&lt;a href="http://search.cpan.org/perldoc?Moose"&gt;Mouse&lt;/a&gt; es un reemplazo de &lt;a href="http://search.cpan.org/perldoc?Moose"&gt;Moose&lt;/a&gt; muy optimizado que permite utilizar la gran mayoría de las características de &lt;a href="http://search.cpan.org/perldoc?Moose"&gt;Moose&lt;/a&gt;, pero es mucho más ligero porque esta desarrollado en XS (es decir en C) y se omiten algunas características para aligerar la ejecución.&lt;br /&gt;&lt;br /&gt;Según la página del manual de &lt;a href="http://search.cpan.org/perldoc?Moose"&gt;Mouse&lt;/a&gt;,  &lt;a href="http://search.cpan.org/perldoc?Moose"&gt;Moose&lt;/a&gt; solamente falla en el 1% de los tests de&amp;nbsp; &lt;a href="http://search.cpan.org/perldoc?Moose"&gt;Mouse&lt;/a&gt;, haciendo al último muy compatible con el primero, pero la batería de pruebas se ejecuta 400% más rápido y en mi experiencia yo no puedo notar la diferencia entre utilizar &lt;a href="http://search.cpan.org/perldoc?Moose"&gt;Mouse&lt;/a&gt; y cosas como Class::Accessor::Fast, y aunque la segunda pudiera ser algo más rápida (algo que no he probado formalmente), tener a disposición un sistema de OOP como &lt;a href="http://search.cpan.org/perldoc?Moose"&gt;Moose&lt;/a&gt; definitivamente vale la pena.&lt;br /&gt;&lt;br /&gt;Usar &lt;a href="http://search.cpan.org/perldoc?Moose"&gt;Mouse&lt;/a&gt; es muy simple, solo hay que cambiar &lt;a href="http://search.cpan.org/perldoc?Moose"&gt;Moose&lt;/a&gt; por &lt;a href="http://search.cpan.org/perldoc?Moose"&gt;Mouse&lt;/a&gt;, todo lo demás sigue igual.&lt;br /&gt;&lt;br /&gt;Las características presentes en Mouse permiten hacer la mayoría de los programas y objetos que necesitas para aplicaciones y herramientas sencillas, y si llegas a necesitar las características adicionales de Moose, como la metaprogramación, Moose es la única opción razonable y no queda otra que pagar el precio de la compilación inicial.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5238463735728501931-7281222996017752837?l=perliscopio.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://perliscopio.blogspot.com/feeds/7281222996017752837/comments/default' title='Enviar comentarios'/><link rel='replies' type='text/html' href='http://perliscopio.blogspot.com/2010/01/moose-de-dieta.html#comment-form' title='0 comentarios'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5238463735728501931/posts/default/7281222996017752837'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5238463735728501931/posts/default/7281222996017752837'/><link rel='alternate' type='text/html' href='http://perliscopio.blogspot.com/2010/01/moose-de-dieta.html' title='Moose de dieta'/><author><name>Jose Rey</name><uri>http://www.blogger.com/profile/15071755167581242815</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5238463735728501931.post-2450216375533690785</id><published>2010-01-18T08:19:00.001-04:30</published><updated>2010-01-18T08:21:04.108-04:30</updated><category scheme='http://www.blogger.com/atom/ns#' term='Perl'/><category scheme='http://www.blogger.com/atom/ns#' term='CPAN'/><category scheme='http://www.blogger.com/atom/ns#' term='Moose'/><title type='text'>Dulce dulce Moose</title><content type='html'>[&lt;a href="http://perliscope.blogspot.com/2010/01/sweeter-moose.html"&gt;English translation&lt;/a&gt;]&lt;br /&gt;&lt;br /&gt;Uno de los comentarios que recibí por el artículo anterior fue acerca de como se vería utilizando la sintaxis de &lt;a href="http://search.cpan.org/perldoc?MooseX::Declare"&gt;MooseX::Declare&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;Este módulo provee extensiones sintácticas que van mucho más allá del azúcar sintáctico regular de Moose.&amp;nbsp; Utilizando la magia negra de &lt;a href="http://search.cpan.org/perldoc?Devel::Declare"&gt;Devel::Declare&lt;/a&gt;, &lt;a href="http://search.cpan.org/perldoc?MooseX::Declare"&gt;MooseX::Declare&lt;/a&gt; crea toda una nueva sintaxis muy similar a la de Perl6, para declarar las clases y roles de Moose, sin embargo, el uso de estas extensiones me genera sentimientos encontrados.&lt;br /&gt;&lt;br /&gt;Por un lado está la apariencia y simplicidad de la sintaxis implementada por el módulo, y por otra parte me he dado cuenta que al cambiar la sintaxis de esta manera dejan de funcionar herramientas que doy por sentadas, como &lt;a href="http://search.cpan.org/perldoc?perltidy"&gt;perltidy&lt;/a&gt;, que da errores en la declaración de prototipos en los métodos, también dejan de funcionar bien módulos como &lt;a href="http://search.cpan.org/perldoc?PPI"&gt;PPI&lt;/a&gt; y hasta el coloreo de vim.&lt;br /&gt;&lt;br /&gt;Estoy consciente de que todo es cuestión de reparar &lt;a href="http://search.cpan.org/perldoc?perltidy"&gt;perltidy&lt;/a&gt;, &lt;a href="http://search.cpan.org/perldoc?PPI"&gt;PPI&lt;/a&gt; y el coloreo de vim, pero el detalle es que es difícil implementar cuanta sintaxis se le ocurra a cualquiera que introduzca nuevos módulos en el CPAN.&lt;br /&gt;&lt;br /&gt;Siempre he argumentado que una de las ventajas de &lt;a href="http://search.cpan.org/perldoc?Devel::Declare"&gt;Devel::Declare&lt;/a&gt; es que permite evolucionar Perl5 a través del CPAN, módulos como &lt;a href="http://search.cpan.org/perldoc?TryCatch"&gt;TryCatch&lt;/a&gt; y &lt;a href="http://search.cpan.org/perldoc?MooseX::Declare"&gt;MooseX::Declare&lt;/a&gt; muestran extensiones sintácticas que en algún momento podrían agregarse a Perl5 de resultar ampliamente aceptadas.&lt;br /&gt;&lt;br /&gt;Pero ¿cómo llegarán a ser ampliamente aceptadas, si no las usamos porque rompen las herramientas que normalmente usamos?&lt;br /&gt;&lt;br /&gt;A lo mejor nada de esto importa porque ya en &lt;a href="http://use.perl.org/%7Epmichaud/journal/39411"&gt;marzo de 2010&lt;/a&gt; llega &lt;a href="http://rakudo.org/"&gt;Rakudo&lt;/a&gt; *, y todo el mundo comenzará la gran migración a Perl6.&lt;br /&gt;&lt;br /&gt;Como en realidad tengo la misma cantidad de argumentos a favor y en contra, voy a seguir meditando en cuales tienen mas peso que otros. Pero mientras tanto aqui tienen la versión de roles del juego de los animales en &lt;a href="http://search.cpan.org/perldoc?MooseX::Declare"&gt;MooseX::Declare&lt;/a&gt;, para que uds. se hagan una idea propia sobre sus costos y beneficios:&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;span style="color: brown;"&gt; 1 &lt;/span&gt;&lt;span style="color: #a020f0;"&gt;#!/usr/bin/env perl&lt;/span&gt;&lt;br /&gt;&lt;span style="color: brown;"&gt; 2 &lt;/span&gt;&lt;span style="color: #a020f0;"&gt;use &lt;/span&gt;MooseX::Declare;&lt;br /&gt;&lt;span style="color: brown;"&gt; 3 &lt;/span&gt;&lt;br /&gt;&lt;span style="color: brown;"&gt; 4 &lt;/span&gt;class QuestionNode {&lt;br /&gt;&lt;span style="color: brown;"&gt; 5 &lt;/span&gt;    has &lt;span style="color: magenta;"&gt;pregunta &lt;/span&gt;=&amp;gt; ( &lt;span style="color: magenta;"&gt;is &lt;/span&gt;=&amp;gt; &lt;span style="color: magenta;"&gt;"&lt;/span&gt;&lt;span style="color: magenta;"&gt;ro&lt;/span&gt;&lt;span style="color: magenta;"&gt;"&lt;/span&gt;, &lt;span style="color: magenta;"&gt;isa &lt;/span&gt;=&amp;gt; &lt;span style="color: magenta;"&gt;"&lt;/span&gt;&lt;span style="color: magenta;"&gt;Str&lt;/span&gt;&lt;span style="color: magenta;"&gt;"&lt;/span&gt;, &lt;span style="color: magenta;"&gt;required &lt;/span&gt;=&amp;gt; &lt;span style="color: magenta;"&gt;1&lt;/span&gt; );&lt;br /&gt;&lt;span style="color: brown;"&gt; 6 &lt;/span&gt;    has [ &lt;span style="color: magenta;"&gt;"&lt;/span&gt;&lt;span style="color: magenta;"&gt;si&lt;/span&gt;&lt;span style="color: magenta;"&gt;"&lt;/span&gt;, &lt;span style="color: magenta;"&gt;"&lt;/span&gt;&lt;span style="color: magenta;"&gt;no&lt;/span&gt;&lt;span style="color: magenta;"&gt;"&lt;/span&gt; ] =&amp;gt; ( &lt;span style="color: magenta;"&gt;is &lt;/span&gt;=&amp;gt; &lt;span style="color: magenta;"&gt;"&lt;/span&gt;&lt;span style="color: magenta;"&gt;rw&lt;/span&gt;&lt;span style="color: magenta;"&gt;"&lt;/span&gt;, &lt;span style="color: magenta;"&gt;isa &lt;/span&gt;=&amp;gt; &lt;span style="color: magenta;"&gt;"&lt;/span&gt;&lt;span style="color: magenta;"&gt;Str|QuestionNode&lt;/span&gt;&lt;span style="color: magenta;"&gt;"&lt;/span&gt;, &lt;span style="color: magenta;"&gt;required &lt;/span&gt;=&amp;gt; &lt;span style="color: magenta;"&gt;1&lt;/span&gt; );&lt;br /&gt;&lt;span style="color: brown;"&gt; 7 &lt;/span&gt;}&lt;br /&gt;&lt;span style="color: brown;"&gt; 8 &lt;/span&gt;&lt;br /&gt;&lt;span style="color: brown;"&gt; 9 &lt;/span&gt;role AnimalsGame {&lt;br /&gt;&lt;span style="color: brown;"&gt;10 &lt;/span&gt;&lt;br /&gt;&lt;span style="color: brown;"&gt;11 &lt;/span&gt;    has &lt;span style="color: magenta;"&gt;tree &lt;/span&gt;=&amp;gt; (&lt;br /&gt;&lt;span style="color: brown;"&gt;12 &lt;/span&gt;        &lt;span style="color: magenta;"&gt;is      &lt;/span&gt;=&amp;gt; &lt;span style="color: magenta;"&gt;"&lt;/span&gt;&lt;span style="color: magenta;"&gt;ro&lt;/span&gt;&lt;span style="color: magenta;"&gt;"&lt;/span&gt;,&lt;br /&gt;&lt;span style="color: brown;"&gt;13 &lt;/span&gt;        &lt;span style="color: magenta;"&gt;isa     &lt;/span&gt;=&amp;gt; &lt;span style="color: magenta;"&gt;"&lt;/span&gt;&lt;span style="color: magenta;"&gt;QuestionNode&lt;/span&gt;&lt;span style="color: magenta;"&gt;"&lt;/span&gt;,&lt;br /&gt;&lt;span style="color: brown;"&gt;14 &lt;/span&gt;        &lt;span style="color: magenta;"&gt;default &lt;/span&gt;=&amp;gt;&lt;span style="color: darkcyan;"&gt; &lt;/span&gt;&lt;span style="color: brown;"&gt;&lt;b&gt;sub&lt;/b&gt;&lt;/span&gt;&lt;span style="color: darkcyan;"&gt; &lt;/span&gt;{&lt;br /&gt;&lt;span style="color: brown;"&gt;15 &lt;/span&gt;            QuestionNode-&amp;gt;&lt;span style="color: brown;"&gt;&lt;b&gt;new&lt;/b&gt;&lt;/span&gt;(&lt;br /&gt;&lt;span style="color: brown;"&gt;16 &lt;/span&gt;                { &lt;span style="color: magenta;"&gt;pregunta &lt;/span&gt;=&amp;gt; &lt;span style="color: magenta;"&gt;'&lt;/span&gt;&lt;span style="color: magenta;"&gt;vive en el agua&lt;/span&gt;&lt;span style="color: magenta;"&gt;'&lt;/span&gt;, &lt;span style="color: magenta;"&gt;no &lt;/span&gt;=&amp;gt; &lt;span style="color: magenta;"&gt;'&lt;/span&gt;&lt;span style="color: magenta;"&gt;tigre&lt;/span&gt;&lt;span style="color: magenta;"&gt;'&lt;/span&gt;, &lt;span style="color: magenta;"&gt;si &lt;/span&gt;=&amp;gt; &lt;span style="color: magenta;"&gt;'&lt;/span&gt;&lt;span style="color: magenta;"&gt;tiburón&lt;/span&gt;&lt;span style="color: magenta;"&gt;'&lt;/span&gt; } );&lt;br /&gt;&lt;span style="color: brown;"&gt;17 &lt;/span&gt;        }&lt;br /&gt;&lt;span style="color: brown;"&gt;18 &lt;/span&gt;    );&lt;br /&gt;&lt;span style="color: brown;"&gt;19 &lt;/span&gt;&lt;br /&gt;&lt;span style="color: brown;"&gt;20 &lt;/span&gt;    method play {&lt;br /&gt;&lt;span style="color: brown;"&gt;21 &lt;/span&gt;        &lt;span style="color: brown;"&gt;&lt;b&gt;my&lt;/b&gt;&lt;/span&gt; &lt;span style="color: darkcyan;"&gt;$guess&lt;/span&gt; = &lt;span style="color: darkcyan;"&gt;$self&lt;/span&gt;&lt;span style="color: darkcyan;"&gt;-&amp;gt;tree&lt;/span&gt;;&lt;br /&gt;&lt;span style="color: brown;"&gt;22 &lt;/span&gt;        &lt;span style="color: brown;"&gt;&lt;b&gt;my&lt;/b&gt;&lt;/span&gt; ( &lt;span style="color: darkcyan;"&gt;$node&lt;/span&gt;, &lt;span style="color: darkcyan;"&gt;$branch&lt;/span&gt; );&lt;br /&gt;&lt;span style="color: brown;"&gt;23 &lt;/span&gt;        &lt;span style="color: brown;"&gt;&lt;b&gt;while&lt;/b&gt;&lt;/span&gt; ( &lt;span style="color: brown;"&gt;&lt;b&gt;ref&lt;/b&gt;&lt;/span&gt;(&lt;span style="color: darkcyan;"&gt;$guess&lt;/span&gt;) ) {&lt;br /&gt;&lt;span style="color: brown;"&gt;24 &lt;/span&gt;            &lt;span style="color: darkcyan;"&gt;$node&lt;/span&gt;   = &lt;span style="color: darkcyan;"&gt;$guess&lt;/span&gt;;&lt;br /&gt;&lt;span style="color: brown;"&gt;25 &lt;/span&gt;            &lt;span style="color: darkcyan;"&gt;$branch&lt;/span&gt; = &lt;span style="color: darkcyan;"&gt;$self&lt;/span&gt;&lt;span style="color: darkcyan;"&gt;-&amp;gt;si&lt;/span&gt;( &lt;span style="color: darkcyan;"&gt;$node&lt;/span&gt;&lt;span style="color: darkcyan;"&gt;-&amp;gt;pregunta&lt;/span&gt; ) ? &lt;span style="color: magenta;"&gt;"&lt;/span&gt;&lt;span style="color: magenta;"&gt;si&lt;/span&gt;&lt;span style="color: magenta;"&gt;"&lt;/span&gt; : &lt;span style="color: magenta;"&gt;"&lt;/span&gt;&lt;span style="color: magenta;"&gt;no&lt;/span&gt;&lt;span style="color: magenta;"&gt;"&lt;/span&gt;;&lt;br /&gt;&lt;span style="color: brown;"&gt;26 &lt;/span&gt;            &lt;span style="color: darkcyan;"&gt;$guess&lt;/span&gt;  = &lt;span style="color: darkcyan;"&gt;$node&lt;/span&gt;-&amp;gt;&lt;span style="color: darkcyan;"&gt;$branch&lt;/span&gt;;&lt;br /&gt;&lt;span style="color: brown;"&gt;27 &lt;/span&gt;        }&lt;br /&gt;&lt;span style="color: brown;"&gt;28 &lt;/span&gt;        &lt;span style="color: brown;"&gt;&lt;b&gt;return&lt;/b&gt;&lt;/span&gt; &lt;span style="color: brown;"&gt;&lt;b&gt;if&lt;/b&gt;&lt;/span&gt; &lt;span style="color: darkcyan;"&gt;$self&lt;/span&gt;&lt;span style="color: darkcyan;"&gt;-&amp;gt;si&lt;/span&gt;(&lt;span style="color: magenta;"&gt;"&lt;/span&gt;&lt;span style="color: magenta;"&gt;Es un(a) &lt;/span&gt;&lt;span style="color: darkcyan;"&gt;$guess&lt;/span&gt;&lt;span style="color: magenta;"&gt;"&lt;/span&gt;);&lt;br /&gt;&lt;span style="color: brown;"&gt;29 &lt;/span&gt;        &lt;span style="color: brown;"&gt;&lt;b&gt;my&lt;/b&gt;&lt;/span&gt; &lt;span style="color: darkcyan;"&gt;$animal&lt;/span&gt; = &lt;span style="color: darkcyan;"&gt;$self&lt;/span&gt;&lt;span style="color: darkcyan;"&gt;-&amp;gt;prompt&lt;/span&gt;(&lt;span style="color: magenta;"&gt;"&lt;/span&gt;&lt;span style="color: magenta;"&gt;Nombre del animal: &lt;/span&gt;&lt;span style="color: magenta;"&gt;"&lt;/span&gt;);&lt;br /&gt;&lt;span style="color: brown;"&gt;30 &lt;/span&gt;        &lt;span style="color: brown;"&gt;&lt;b&gt;my&lt;/b&gt;&lt;/span&gt; &lt;span style="color: darkcyan;"&gt;$diff&lt;/span&gt;   = &lt;span style="color: darkcyan;"&gt;$self&lt;/span&gt;&lt;span style="color: darkcyan;"&gt;-&amp;gt;prompt&lt;/span&gt;(&lt;br /&gt;&lt;span style="color: brown;"&gt;31 &lt;/span&gt;            &lt;span style="color: magenta;"&gt;"&lt;/span&gt;&lt;span style="color: magenta;"&gt;Una pregunta cierta para &lt;/span&gt;&lt;span style="color: darkcyan;"&gt;$animal&lt;/span&gt;&lt;span style="color: magenta;"&gt; pero falsa para &lt;/span&gt;&lt;span style="color: darkcyan;"&gt;$guess&lt;/span&gt;&lt;span style="color: magenta;"&gt;: &lt;/span&gt;&lt;span style="color: magenta;"&gt;"&lt;/span&gt;);&lt;br /&gt;&lt;span style="color: brown;"&gt;32 &lt;/span&gt;        &lt;span style="color: darkcyan;"&gt;$node&lt;/span&gt;-&amp;gt;&lt;span style="color: darkcyan;"&gt;$branch&lt;/span&gt;( QuestionNode-&amp;gt;&lt;span style="color: brown;"&gt;&lt;b&gt;new&lt;/b&gt;&lt;/span&gt;( { &lt;span style="color: magenta;"&gt;pregunta &lt;/span&gt;=&amp;gt; &lt;span style="color: darkcyan;"&gt;$diff&lt;/span&gt;, &lt;span style="color: magenta;"&gt;no &lt;/span&gt;=&amp;gt; &lt;span style="color: darkcyan;"&gt;$guess&lt;/span&gt;, &lt;span style="color: magenta;"&gt;si &lt;/span&gt;=&amp;gt; &lt;span style="color: darkcyan;"&gt;$animal&lt;/span&gt; } ) );&lt;br /&gt;&lt;span style="color: brown;"&gt;33 &lt;/span&gt;    }&lt;br /&gt;&lt;span style="color: brown;"&gt;34 &lt;/span&gt;&lt;br /&gt;&lt;span style="color: brown;"&gt;35 &lt;/span&gt;}&lt;br /&gt;&lt;span style="color: brown;"&gt;36 &lt;/span&gt;&lt;br /&gt;&lt;span style="color: brown;"&gt;37 &lt;/span&gt;role ConsoleGame {&lt;br /&gt;&lt;span style="color: brown;"&gt;38 &lt;/span&gt;    &lt;span style="color: #a020f0;"&gt;use &lt;/span&gt;Term::ReadLine;&lt;br /&gt;&lt;span style="color: brown;"&gt;39 &lt;/span&gt;    &lt;span style="color: #a020f0;"&gt;use &lt;/span&gt;IO::Handle;&lt;br /&gt;&lt;span style="color: brown;"&gt;40 &lt;/span&gt;&lt;br /&gt;&lt;span style="color: brown;"&gt;41 &lt;/span&gt;    has &lt;span style="color: magenta;"&gt;title &lt;/span&gt;=&amp;gt; ( &lt;span style="color: magenta;"&gt;is &lt;/span&gt;=&amp;gt; &lt;span style="color: magenta;"&gt;"&lt;/span&gt;&lt;span style="color: magenta;"&gt;ro&lt;/span&gt;&lt;span style="color: magenta;"&gt;"&lt;/span&gt;, &lt;span style="color: magenta;"&gt;isa &lt;/span&gt;=&amp;gt; &lt;span style="color: magenta;"&gt;"&lt;/span&gt;&lt;span style="color: magenta;"&gt;Str&lt;/span&gt;&lt;span style="color: magenta;"&gt;"&lt;/span&gt;, &lt;span style="color: magenta;"&gt;default &lt;/span&gt;=&amp;gt; &lt;span style="color: magenta;"&gt;"&lt;/span&gt;&lt;span style="color: magenta;"&gt;El juego de los animales&lt;/span&gt;&lt;span style="color: magenta;"&gt;"&lt;/span&gt; );&lt;br /&gt;&lt;span style="color: brown;"&gt;42 &lt;/span&gt;    has &lt;span style="color: magenta;"&gt;term &lt;/span&gt;=&amp;gt; (&lt;br /&gt;&lt;span style="color: brown;"&gt;43 &lt;/span&gt;        &lt;span style="color: magenta;"&gt;is         &lt;/span&gt;=&amp;gt; &lt;span style="color: magenta;"&gt;"&lt;/span&gt;&lt;span style="color: magenta;"&gt;ro&lt;/span&gt;&lt;span style="color: magenta;"&gt;"&lt;/span&gt;,&lt;br /&gt;&lt;span style="color: brown;"&gt;44 &lt;/span&gt;        &lt;span style="color: magenta;"&gt;isa        &lt;/span&gt;=&amp;gt; &lt;span style="color: magenta;"&gt;"&lt;/span&gt;&lt;span style="color: magenta;"&gt;Object&lt;/span&gt;&lt;span style="color: magenta;"&gt;"&lt;/span&gt;,&lt;br /&gt;&lt;span style="color: brown;"&gt;45 &lt;/span&gt;        &lt;span style="color: magenta;"&gt;lazy_build &lt;/span&gt;=&amp;gt; &lt;span style="color: magenta;"&gt;1&lt;/span&gt;,&lt;br /&gt;&lt;span style="color: brown;"&gt;46 &lt;/span&gt;        &lt;span style="color: magenta;"&gt;handles    &lt;/span&gt;=&amp;gt; { &lt;span style="color: magenta;"&gt;prompt &lt;/span&gt;=&amp;gt; &lt;span style="color: magenta;"&gt;"&lt;/span&gt;&lt;span style="color: magenta;"&gt;readline&lt;/span&gt;&lt;span style="color: magenta;"&gt;"&lt;/span&gt; }&lt;br /&gt;&lt;span style="color: brown;"&gt;47 &lt;/span&gt;    );&lt;br /&gt;&lt;span style="color: brown;"&gt;48 &lt;/span&gt;&lt;br /&gt;&lt;span style="color: brown;"&gt;49 &lt;/span&gt;    method _build_term {&lt;br /&gt;&lt;span style="color: brown;"&gt;50 &lt;/span&gt;        Term::ReadLine-&amp;gt;&lt;span style="color: brown;"&gt;&lt;b&gt;new&lt;/b&gt;&lt;/span&gt;( &lt;span style="color: darkcyan;"&gt;$self&lt;/span&gt;&lt;span style="color: darkcyan;"&gt;-&amp;gt;title&lt;/span&gt; );&lt;br /&gt;&lt;span style="color: brown;"&gt;51 &lt;/span&gt;    }&lt;br /&gt;&lt;span style="color: brown;"&gt;52 &lt;/span&gt;&lt;br /&gt;&lt;span style="color: brown;"&gt;53 &lt;/span&gt;    method si(Str &lt;span style="color: darkcyan;"&gt;$prompt&lt;/span&gt;) {&lt;br /&gt;&lt;span style="color: brown;"&gt;54 &lt;/span&gt;        &lt;span style="color: brown;"&gt;&lt;b&gt;while&lt;/b&gt;&lt;/span&gt; (&lt;span style="color: magenta;"&gt;1&lt;/span&gt;) {&lt;br /&gt;&lt;span style="color: brown;"&gt;55 &lt;/span&gt;            &lt;span style="color: brown;"&gt;&lt;b&gt;my&lt;/b&gt;&lt;/span&gt; &lt;span style="color: darkcyan;"&gt;$answer&lt;/span&gt; = &lt;span style="color: darkcyan;"&gt;$self&lt;/span&gt;&lt;span style="color: darkcyan;"&gt;-&amp;gt;prompt&lt;/span&gt;(&lt;span style="color: magenta;"&gt;"&lt;/span&gt;&lt;span style="color: darkcyan;"&gt;$prompt&lt;/span&gt;&lt;span style="color: magenta;"&gt;? (y/n): &lt;/span&gt;&lt;span style="color: magenta;"&gt;"&lt;/span&gt;);&lt;br /&gt;&lt;span style="color: brown;"&gt;56 &lt;/span&gt;            &lt;span style="color: brown;"&gt;&lt;b&gt;return&lt;/b&gt;&lt;/span&gt; ( &lt;span style="color: darkcyan;"&gt;$2&lt;/span&gt; ? &lt;span style="color: magenta;"&gt;1&lt;/span&gt; : &lt;span style="color: magenta;"&gt;0&lt;/span&gt; ) &lt;span style="color: brown;"&gt;&lt;b&gt;if&lt;/b&gt;&lt;/span&gt; &lt;span style="color: darkcyan;"&gt;$answer&lt;/span&gt; =~&lt;span style="color: brown;"&gt;&lt;b&gt; /&lt;/b&gt;&lt;/span&gt;&lt;span style="color: magenta;"&gt;^&lt;/span&gt;&lt;span style="color: slateblue;"&gt;\s&lt;/span&gt;&lt;span style="color: slateblue;"&gt;*((&lt;/span&gt;&lt;span style="color: magenta;"&gt;si|s&lt;/span&gt;&lt;span style="color: slateblue;"&gt;)&lt;/span&gt;&lt;span style="color: magenta;"&gt;|&lt;/span&gt;&lt;span style="color: slateblue;"&gt;(&lt;/span&gt;&lt;span style="color: magenta;"&gt;no|n&lt;/span&gt;&lt;span style="color: slateblue;"&gt;))&lt;/span&gt;&lt;span style="color: slateblue;"&gt;\s&lt;/span&gt;&lt;span style="color: slateblue;"&gt;*&lt;/span&gt;&lt;span style="color: brown;"&gt;&lt;b&gt;/i&lt;/b&gt;&lt;/span&gt;;&lt;br /&gt;&lt;span style="color: brown;"&gt;57 &lt;/span&gt;            &lt;span style="color: darkcyan;"&gt;$self&lt;/span&gt;&lt;span style="color: darkcyan;"&gt;-&amp;gt;term&lt;/span&gt;-&amp;gt;OUT-&amp;gt;&lt;span style="color: brown;"&gt;&lt;b&gt;print&lt;/b&gt;&lt;/span&gt;(&lt;span style="color: magenta;"&gt;"&lt;/span&gt;&lt;span style="color: magenta;"&gt;Responde 's' o 'n'&lt;/span&gt;&lt;span style="color: slateblue;"&gt;\n&lt;/span&gt;&lt;span style="color: magenta;"&gt;"&lt;/span&gt;);&lt;br /&gt;&lt;span style="color: brown;"&gt;58 &lt;/span&gt;        }&lt;br /&gt;&lt;span style="color: brown;"&gt;59 &lt;/span&gt;    }&lt;br /&gt;&lt;span style="color: brown;"&gt;60 &lt;/span&gt;&lt;br /&gt;&lt;span style="color: brown;"&gt;61 &lt;/span&gt;    method run {&lt;br /&gt;&lt;span style="color: brown;"&gt;62 &lt;/span&gt;        &lt;span style="color: darkcyan;"&gt;$self&lt;/span&gt;&lt;span style="color: darkcyan;"&gt;-&amp;gt;play&lt;/span&gt;;&lt;br /&gt;&lt;span style="color: brown;"&gt;63 &lt;/span&gt;        &lt;span style="color: darkcyan;"&gt;$self&lt;/span&gt;&lt;span style="color: darkcyan;"&gt;-&amp;gt;play&lt;/span&gt; &lt;span style="color: brown;"&gt;&lt;b&gt;while&lt;/b&gt;&lt;/span&gt; &lt;span style="color: darkcyan;"&gt;$self&lt;/span&gt;&lt;span style="color: darkcyan;"&gt;-&amp;gt;si&lt;/span&gt;(&lt;span style="color: magenta;"&gt;"&lt;/span&gt;&lt;span style="color: magenta;"&gt;Quieres jugar de nuevo&lt;/span&gt;&lt;span style="color: magenta;"&gt;"&lt;/span&gt;);&lt;br /&gt;&lt;span style="color: brown;"&gt;64 &lt;/span&gt;    }&lt;br /&gt;&lt;span style="color: brown;"&gt;65 &lt;/span&gt;}&lt;br /&gt;&lt;span style="color: brown;"&gt;66 &lt;/span&gt;&lt;br /&gt;&lt;span style="color: brown;"&gt;67 &lt;/span&gt;class Game with AnimalsGame with ConsoleGame {}&lt;br /&gt;&lt;span style="color: brown;"&gt;68 &lt;/span&gt;&lt;br /&gt;&lt;span style="color: brown;"&gt;69 &lt;/span&gt;Game-&amp;gt;&lt;span style="color: brown;"&gt;&lt;b&gt;new&lt;/b&gt;&lt;/span&gt;-&amp;gt;run;&lt;br /&gt;&lt;/pre&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5238463735728501931-2450216375533690785?l=perliscopio.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://perliscopio.blogspot.com/feeds/2450216375533690785/comments/default' title='Enviar comentarios'/><link rel='replies' type='text/html' href='http://perliscopio.blogspot.com/2010/01/dulce-dulce-moose.html#comment-form' title='0 comentarios'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5238463735728501931/posts/default/2450216375533690785'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5238463735728501931/posts/default/2450216375533690785'/><link rel='alternate' type='text/html' href='http://perliscopio.blogspot.com/2010/01/dulce-dulce-moose.html' title='Dulce dulce Moose'/><author><name>Jose Rey</name><uri>http://www.blogger.com/profile/15071755167581242815</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5238463735728501931.post-9058356365545384379</id><published>2010-01-11T00:44:00.001-04:30</published><updated>2010-01-11T00:46:59.899-04:30</updated><category scheme='http://www.blogger.com/atom/ns#' term='Perl'/><category scheme='http://www.blogger.com/atom/ns#' term='CPAN'/><category scheme='http://www.blogger.com/atom/ns#' term='Moose'/><title type='text'>Evolución del estilo en Perl</title><content type='html'>[&lt;a href="http://perliscope.blogspot.com/2010/01/programming-style-evolution-in-perl.html"&gt;English translation&lt;/a&gt;]&lt;br /&gt;&lt;br /&gt;Las técnicas y el estilo en la programación es una de esas cosas que van cambiando con el tiempo, como Perl permite extender el lenguaje con facilidad, se forma un círculo evolutivo cuando a su vez las extensiones popularizan nuevos estilos de programación.&lt;br /&gt;&lt;br /&gt;Hoy intento dar un rápido vistazo a varias maneras de programar en Perl que he utilizado durante los años, con la esperanza de que podáis apreciar las ventajas del estilo de la programación moderna en Perl.&lt;br /&gt;&lt;br /&gt;Todos los programas de este artículo tienen el mismo objetivo, jugar el juego de los animales, que da la ilusión de que la computadora aprende. Sin embargo, no todos los programas utilizan las mismas estructuras de datos o logran el mismo nivel de robustez, en este sentido los estilos "antiguos" son menos robustos que los modernos.&lt;br /&gt;&lt;br /&gt;&lt;h2&gt;Perl5 Antiguo&lt;/h2&gt;&lt;br /&gt;En los principios de Perl5 las computadoras tenían menos capacidad, así que los programas solían escribirse de manera bastante compacta, además se usaban "trucos inteligentes", como el uso de los hashes en este programa, en el cual no es fácil comprender como funciona exactamente %tree en el programa:&lt;br /&gt;&lt;br /&gt;Estilo 1: Antiguo&lt;br /&gt;&lt;pre&gt;&lt;span style="color: brown;"&gt; 1 &lt;/span&gt;&lt;span style="color: #a020f0;"&gt;#!/usr/bin/env perl&lt;/span&gt;&lt;br /&gt;&lt;span style="color: brown;"&gt; 2 &lt;/span&gt;&lt;span style="color: brown;"&gt;&lt;b&gt;sub&lt;/b&gt;&lt;/span&gt;&lt;span style="color: darkcyan;"&gt; &lt;/span&gt;&lt;span style="color: darkcyan;"&gt;prompt &lt;/span&gt;{&lt;br /&gt;&lt;span style="color: brown;"&gt; 3 &lt;/span&gt;    &lt;span style="color: brown;"&gt;&lt;b&gt;print&lt;/b&gt;&lt;/span&gt; &lt;span style="color: darkcyan;"&gt;$_[&lt;/span&gt;&lt;span style="color: magenta;"&gt;0&lt;/span&gt;&lt;span style="color: darkcyan;"&gt;]&lt;/span&gt;;&lt;br /&gt;&lt;span style="color: brown;"&gt; 4 &lt;/span&gt;    &lt;span style="color: darkcyan;"&gt;$line&lt;/span&gt; = &amp;lt;&amp;gt;;&lt;br /&gt;&lt;span style="color: brown;"&gt; 5 &lt;/span&gt;    &lt;span style="color: brown;"&gt;&lt;b&gt;chomp&lt;/b&gt;&lt;/span&gt; &lt;span style="color: darkcyan;"&gt;$line&lt;/span&gt;;&lt;br /&gt;&lt;span style="color: brown;"&gt; 6 &lt;/span&gt;    &lt;span style="color: darkcyan;"&gt;$line&lt;/span&gt;;&lt;br /&gt;&lt;span style="color: brown;"&gt; 7 &lt;/span&gt;}&lt;br /&gt;&lt;span style="color: brown;"&gt; 8 &lt;/span&gt;&lt;br /&gt;&lt;span style="color: brown;"&gt; 9 &lt;/span&gt;&lt;span style="color: brown;"&gt;&lt;b&gt;sub&lt;/b&gt;&lt;/span&gt;&lt;span style="color: darkcyan;"&gt; &lt;/span&gt;&lt;span style="color: darkcyan;"&gt;si &lt;/span&gt;{&lt;br /&gt;&lt;span style="color: brown;"&gt;10 &lt;/span&gt;    prompt(&lt;span style="color: magenta;"&gt;"&lt;/span&gt;&lt;span style="color: darkcyan;"&gt;$_[&lt;/span&gt;&lt;span style="color: magenta;"&gt;0&lt;/span&gt;&lt;span style="color: darkcyan;"&gt;]&lt;/span&gt;&lt;span style="color: magenta;"&gt;? (s/n): &lt;/span&gt;&lt;span style="color: magenta;"&gt;"&lt;/span&gt;) =~&lt;span style="color: brown;"&gt;&lt;b&gt; /&lt;/b&gt;&lt;/span&gt;&lt;span style="color: magenta;"&gt;^&lt;/span&gt;&lt;span style="color: slateblue;"&gt;\s&lt;/span&gt;&lt;span style="color: slateblue;"&gt;*&lt;/span&gt;&lt;span style="color: magenta;"&gt;s&lt;/span&gt;&lt;span style="color: brown;"&gt;&lt;b&gt;/i&lt;/b&gt;&lt;/span&gt;;&lt;br /&gt;&lt;span style="color: brown;"&gt;11 &lt;/span&gt;}&lt;br /&gt;&lt;span style="color: brown;"&gt;12 &lt;/span&gt;&lt;br /&gt;&lt;span style="color: brown;"&gt;13 &lt;/span&gt;&lt;span style="color: darkcyan;"&gt;$pregunta&lt;/span&gt; = &lt;span style="color: darkcyan;"&gt;$root&lt;/span&gt; = &lt;span style="color: magenta;"&gt;"&lt;/span&gt;&lt;span style="color: magenta;"&gt;vive en el agua&lt;/span&gt;&lt;span style="color: magenta;"&gt;"&lt;/span&gt;;&lt;br /&gt;&lt;span style="color: brown;"&gt;14 &lt;/span&gt;&lt;span style="color: darkcyan;"&gt;%tree&lt;/span&gt; = ( &lt;span style="color: darkcyan;"&gt;$root&lt;/span&gt; =&amp;gt; [ &lt;span style="color: magenta;"&gt;'&lt;/span&gt;&lt;span style="color: magenta;"&gt;tigre&lt;/span&gt;&lt;span style="color: magenta;"&gt;'&lt;/span&gt;, &lt;span style="color: magenta;"&gt;'&lt;/span&gt;&lt;span style="color: magenta;"&gt;tiburón&lt;/span&gt;&lt;span style="color: magenta;"&gt;'&lt;/span&gt; ] );&lt;br /&gt;&lt;span style="color: brown;"&gt;15 &lt;/span&gt;&lt;span style="color: brown;"&gt;&lt;b&gt;do&lt;/b&gt;&lt;/span&gt; {&lt;br /&gt;&lt;span style="color: brown;"&gt;16 &lt;/span&gt;    {&lt;br /&gt;&lt;span style="color: brown;"&gt;17 &lt;/span&gt;        &lt;span style="color: darkcyan;"&gt;$branch&lt;/span&gt;   = si(&lt;span style="color: darkcyan;"&gt;$pregunta&lt;/span&gt;);&lt;br /&gt;&lt;span style="color: brown;"&gt;18 &lt;/span&gt;        &lt;span style="color: darkcyan;"&gt;$guess&lt;/span&gt;    = &lt;span style="color: darkcyan;"&gt;$tree{$pregunta}[$branch]&lt;/span&gt;;&lt;br /&gt;&lt;span style="color: brown;"&gt;19 &lt;/span&gt;        &lt;span style="color: darkcyan;"&gt;$pregunta&lt;/span&gt; = &lt;span style="color: darkcyan;"&gt;$guess&lt;/span&gt;, &lt;span style="color: brown;"&gt;&lt;b&gt;redo&lt;/b&gt;&lt;/span&gt; &lt;span style="color: brown;"&gt;&lt;b&gt;if&lt;/b&gt;&lt;/span&gt; &lt;span style="color: darkcyan;"&gt;$tree{$guess}&lt;/span&gt;;&lt;br /&gt;&lt;span style="color: brown;"&gt;20 &lt;/span&gt;        &lt;span style="color: darkcyan;"&gt;$pregunta&lt;/span&gt; = &lt;span style="color: darkcyan;"&gt;$root&lt;/span&gt;, &lt;span style="color: brown;"&gt;&lt;b&gt;next&lt;/b&gt;&lt;/span&gt; &lt;span style="color: brown;"&gt;&lt;b&gt;if&lt;/b&gt;&lt;/span&gt; si(&lt;span style="color: magenta;"&gt;"&lt;/span&gt;&lt;span style="color: magenta;"&gt;Es un(a) &lt;/span&gt;&lt;span style="color: darkcyan;"&gt;$guess&lt;/span&gt;&lt;span style="color: magenta;"&gt;"&lt;/span&gt;);&lt;br /&gt;&lt;span style="color: brown;"&gt;21 &lt;/span&gt;        &lt;span style="color: darkcyan;"&gt;$animal&lt;/span&gt;   = prompt(&lt;span style="color: magenta;"&gt;"&lt;/span&gt;&lt;span style="color: magenta;"&gt;Nombre del animal: &lt;/span&gt;&lt;span style="color: magenta;"&gt;"&lt;/span&gt;);&lt;br /&gt;&lt;span style="color: brown;"&gt;22 &lt;/span&gt;        &lt;span style="color: darkcyan;"&gt;$diff&lt;/span&gt;     = prompt( &lt;span style="color: magenta;"&gt;"&lt;/span&gt;&lt;span style="color: magenta;"&gt;Una pregunta cierta para &lt;/span&gt;&lt;span style="color: darkcyan;"&gt;$animal&lt;/span&gt;&lt;span style="color: magenta;"&gt;"&lt;/span&gt; .&lt;br /&gt;&lt;span style="color: brown;"&gt;23 &lt;/span&gt;                            &lt;span style="color: magenta;"&gt;"&lt;/span&gt;&lt;span style="color: magenta;"&gt; pero falsa para &lt;/span&gt;&lt;span style="color: darkcyan;"&gt;$guess&lt;/span&gt;&lt;span style="color: magenta;"&gt;: &lt;/span&gt;&lt;span style="color: magenta;"&gt;"&lt;/span&gt; );&lt;br /&gt;&lt;span style="color: brown;"&gt;24 &lt;/span&gt;        &lt;span style="color: darkcyan;"&gt;$tree{$diff}&lt;/span&gt; = [ &lt;span style="color: darkcyan;"&gt;$tree{$pregunta}[$branch]&lt;/span&gt;, &lt;span style="color: darkcyan;"&gt;$animal&lt;/span&gt; ];&lt;br /&gt;&lt;span style="color: brown;"&gt;25 &lt;/span&gt;        &lt;span style="color: darkcyan;"&gt;$tree{$pregunta}[$branch]&lt;/span&gt; = &lt;span style="color: darkcyan;"&gt;$diff&lt;/span&gt;;&lt;br /&gt;&lt;span style="color: brown;"&gt;26 &lt;/span&gt;        &lt;span style="color: darkcyan;"&gt;$pregunta&lt;/span&gt; = &lt;span style="color: darkcyan;"&gt;$root&lt;/span&gt;&lt;br /&gt;&lt;span style="color: brown;"&gt;27 &lt;/span&gt;    }&lt;br /&gt;&lt;span style="color: brown;"&gt;28 &lt;/span&gt;} &lt;span style="color: brown;"&gt;&lt;b&gt;while&lt;/b&gt;&lt;/span&gt; si(&lt;span style="color: magenta;"&gt;"&lt;/span&gt;&lt;span style="color: magenta;"&gt;Quieres jugar de nuevo&lt;/span&gt;&lt;span style="color: magenta;"&gt;"&lt;/span&gt;);&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;Son programas como esos lo que le dieron la (mala) fama de lenguaje de solo escritura. Sin embargo por aquellos días se valoraba mucho la inteligencia, y se inventaron los torneos de golf (la comunidad de Perl es la única que conozco que ha jugado golf con el lenguaje). En un partido de golf el programa anterior podría terminar fácilmente como se muestra a continuación:&lt;br /&gt;&lt;br /&gt;Estilo 2: Golf&lt;br /&gt;&lt;pre&gt;&lt;span style="color: brown;"&gt;1 &lt;/span&gt;&lt;span style="color: #a020f0;"&gt;#!/usr/bin/env perl&lt;/span&gt;&lt;br /&gt;&lt;span style="color: brown;"&gt;2 &lt;/span&gt;&lt;span style="color: brown;"&gt;&lt;b&gt;sub&lt;/b&gt;&lt;/span&gt;&lt;span style="color: darkcyan;"&gt; &lt;/span&gt;&lt;span style="color: darkcyan;"&gt;p{print$_[&lt;/span&gt;&lt;span style="color: darkcyan;"&gt;0]&lt;/span&gt;;&lt;span style="color: darkcyan;"&gt;$l&lt;/span&gt;=&amp;lt;&amp;gt;;&lt;span style="color: brown;"&gt;&lt;b&gt;chomp&lt;/b&gt;&lt;/span&gt;&lt;span style="color: darkcyan;"&gt;$l&lt;/span&gt;;&lt;span style="color: darkcyan;"&gt;$l&lt;/span&gt;}&lt;span style="color: brown;"&gt;&lt;b&gt;sub&lt;/b&gt;&lt;/span&gt;&lt;span style="color: darkcyan;"&gt; &lt;/span&gt;&lt;span style="color: darkcyan;"&gt;a{p(&lt;/span&gt;&lt;span style="color: darkcyan;"&gt;"$&lt;/span&gt;&lt;span style="color: darkcyan;"&gt;_[&lt;/span&gt;&lt;span style="color: darkcyan;"&gt;0]? &lt;/span&gt;&lt;span style="color: darkcyan;"&gt;(s/n)&lt;/span&gt;&lt;span style="color: darkcyan;"&gt;: ")=~/^\&lt;/span&gt;&lt;span style="color: darkcyan;"&gt;s*s/i}&lt;/span&gt;&lt;span style="color: darkcyan;"&gt;$&lt;/span&gt;&lt;span style="color: darkcyan;"&gt;q=&lt;/span&gt;&lt;br /&gt;&lt;span style="color: brown;"&gt;3 &lt;/span&gt;&lt;span style="color: darkcyan;"&gt;$&lt;/span&gt;&lt;span style="color: darkcyan;"&gt;s=&lt;/span&gt;&lt;span style="color: darkcyan;"&gt;"&lt;/span&gt;&lt;span style="color: darkcyan;"&gt;vive en el agua"&lt;/span&gt;;&lt;span style="color: darkcyan;"&gt;%t&lt;/span&gt;=(&lt;span style="color: darkcyan;"&gt;$s&lt;/span&gt;=&amp;gt;[&lt;span style="color: magenta;"&gt;"&lt;/span&gt;&lt;span style="color: magenta;"&gt;tigre&lt;/span&gt;&lt;span style="color: magenta;"&gt;"&lt;/span&gt;,&lt;span style="color: magenta;"&gt;"&lt;/span&gt;&lt;span style="color: magenta;"&gt;tiburón&lt;/span&gt;&lt;span style="color: magenta;"&gt;"&lt;/span&gt;]);&lt;span style="color: brown;"&gt;&lt;b&gt;do&lt;/b&gt;&lt;/span&gt; {{&lt;span style="color: darkcyan;"&gt;$v&lt;/span&gt;=a(&lt;span style="color: darkcyan;"&gt;$q&lt;/span&gt;);&lt;span style="color: darkcyan;"&gt;$a&lt;/span&gt;=&lt;span style="color: darkcyan;"&gt;$t{$q}[$v]&lt;/span&gt;;&lt;br /&gt;&lt;span style="color: brown;"&gt;4 &lt;/span&gt;&lt;span style="color: darkcyan;"&gt;$q&lt;/span&gt;=&lt;span style="color: darkcyan;"&gt;$a&lt;/span&gt;,&lt;span style="color: brown;"&gt;&lt;b&gt;redo&lt;/b&gt;&lt;/span&gt; &lt;span style="color: brown;"&gt;&lt;b&gt;if&lt;/b&gt;&lt;/span&gt;&lt;span style="color: darkcyan;"&gt;$t{$a}&lt;/span&gt;;&lt;span style="color: darkcyan;"&gt;$q&lt;/span&gt;=&lt;span style="color: darkcyan;"&gt;$s&lt;/span&gt;,&lt;span style="color: brown;"&gt;&lt;b&gt;next&lt;/b&gt;&lt;/span&gt; &lt;span style="color: brown;"&gt;&lt;b&gt;if&lt;/b&gt;&lt;/span&gt; a&lt;span style="color: magenta;"&gt;"&lt;/span&gt;&lt;span style="color: magenta;"&gt;Es un(a) &lt;/span&gt;&lt;span style="color: darkcyan;"&gt;$a&lt;/span&gt;&lt;span style="color: magenta;"&gt;"&lt;/span&gt;;&lt;span style="color: darkcyan;"&gt;$n&lt;/span&gt;=p&lt;span style="color: magenta;"&gt;"&lt;/span&gt;&lt;span style="color: magenta;"&gt;Nombre del animal: &lt;/span&gt;&lt;span style="color: magenta;"&gt;"&lt;/span&gt;;&lt;br /&gt;&lt;span style="color: brown;"&gt;5 &lt;/span&gt;&lt;span style="color: darkcyan;"&gt;$o&lt;/span&gt;=p&lt;span style="color: magenta;"&gt;"&lt;/span&gt;&lt;span style="color: magenta;"&gt;Una pregunta cierta para &lt;/span&gt;&lt;span style="color: darkcyan;"&gt;$n&lt;/span&gt;&lt;span style="color: magenta;"&gt; pero falsa para &lt;/span&gt;&lt;span style="color: darkcyan;"&gt;$a&lt;/span&gt;&lt;span style="color: magenta;"&gt;: &lt;/span&gt;&lt;span style="color: magenta;"&gt;"&lt;/span&gt;;&lt;span style="color: darkcyan;"&gt;$t{$o}&lt;/span&gt;&lt;br /&gt;&lt;span style="color: brown;"&gt;6 &lt;/span&gt;=[&lt;span style="color: darkcyan;"&gt;$t{$q}[$v]&lt;/span&gt;,&lt;span style="color: darkcyan;"&gt;$n&lt;/span&gt;];&lt;span style="color: darkcyan;"&gt;$t{$q}[$v]&lt;/span&gt;=&lt;span style="color: darkcyan;"&gt;$o&lt;/span&gt;;&lt;span style="color: darkcyan;"&gt;$q&lt;/span&gt;=&lt;span style="color: darkcyan;"&gt;$s&lt;/span&gt;}}&lt;span style="color: brown;"&gt;&lt;b&gt;while&lt;/b&gt;&lt;/span&gt; a&lt;span style="color: magenta;"&gt;"&lt;/span&gt;&lt;span style="color: magenta;"&gt;Quieres jugar de nuevo&lt;/span&gt;&lt;span style="color: magenta;"&gt;"&lt;/span&gt;;&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;Como te imaginarás, programas como el anterior solo lograron empeorar la situación,pues la práctica de este estilo terminó en lugares donde no debió usarse,programas que necesitaban mantenimiento y que por supuesto eran difíciles de mantener. Aun utilizando herramientas como perltidy que reformatean por completo el programa haciendo visible su estructura, es difícil comprenderlo:&lt;br /&gt;&lt;br /&gt;Estilo 3: Sucinto&lt;br /&gt;&lt;pre&gt;&lt;span style="color: brown;"&gt; 1 &lt;/span&gt;&lt;span style="color: #a020f0;"&gt;#!/usr/bin/env perl&lt;/span&gt;&lt;br /&gt;&lt;span style="color: brown;"&gt; 2 &lt;/span&gt;&lt;span style="color: brown;"&gt;&lt;b&gt;sub&lt;/b&gt;&lt;/span&gt;&lt;span style="color: darkcyan;"&gt; &lt;/span&gt;&lt;span style="color: darkcyan;"&gt;p &lt;/span&gt;{ &lt;span style="color: brown;"&gt;&lt;b&gt;print&lt;/b&gt;&lt;/span&gt; &lt;span style="color: darkcyan;"&gt;$_[&lt;/span&gt;&lt;span style="color: magenta;"&gt;0&lt;/span&gt;&lt;span style="color: darkcyan;"&gt;]&lt;/span&gt;; &lt;span style="color: darkcyan;"&gt;$l&lt;/span&gt; = &amp;lt;&amp;gt;; &lt;span style="color: brown;"&gt;&lt;b&gt;chomp&lt;/b&gt;&lt;/span&gt; &lt;span style="color: darkcyan;"&gt;$l&lt;/span&gt;; &lt;span style="color: darkcyan;"&gt;$l&lt;/span&gt; }&lt;br /&gt;&lt;span style="color: brown;"&gt; 3 &lt;/span&gt;&lt;span style="color: brown;"&gt;&lt;b&gt;sub&lt;/b&gt;&lt;/span&gt;&lt;span style="color: darkcyan;"&gt; &lt;/span&gt;&lt;span style="color: darkcyan;"&gt;a &lt;/span&gt;{ p(&lt;span style="color: magenta;"&gt;"&lt;/span&gt;&lt;span style="color: darkcyan;"&gt;$_[&lt;/span&gt;&lt;span style="color: magenta;"&gt;0&lt;/span&gt;&lt;span style="color: darkcyan;"&gt;]&lt;/span&gt;&lt;span style="color: magenta;"&gt;? (s/n): &lt;/span&gt;&lt;span style="color: magenta;"&gt;"&lt;/span&gt;) =~&lt;span style="color: brown;"&gt;&lt;b&gt; /&lt;/b&gt;&lt;/span&gt;&lt;span style="color: magenta;"&gt;^&lt;/span&gt;&lt;span style="color: slateblue;"&gt;\s&lt;/span&gt;&lt;span style="color: slateblue;"&gt;*&lt;/span&gt;&lt;span style="color: magenta;"&gt;s&lt;/span&gt;&lt;span style="color: brown;"&gt;&lt;b&gt;/i&lt;/b&gt;&lt;/span&gt; }&lt;br /&gt;&lt;span style="color: brown;"&gt; 4 &lt;/span&gt;&lt;span style="color: darkcyan;"&gt;$q&lt;/span&gt; = &lt;span style="color: darkcyan;"&gt;$s&lt;/span&gt; = &lt;span style="color: magenta;"&gt;"&lt;/span&gt;&lt;span style="color: magenta;"&gt;vive en el agua&lt;/span&gt;&lt;span style="color: magenta;"&gt;"&lt;/span&gt;;&lt;br /&gt;&lt;span style="color: brown;"&gt; 5 &lt;/span&gt;&lt;span style="color: darkcyan;"&gt;%t&lt;/span&gt; = ( &lt;span style="color: darkcyan;"&gt;$s&lt;/span&gt; =&amp;gt; [ &lt;span style="color: magenta;"&gt;"&lt;/span&gt;&lt;span style="color: magenta;"&gt;tigre&lt;/span&gt;&lt;span style="color: magenta;"&gt;"&lt;/span&gt;, &lt;span style="color: magenta;"&gt;"&lt;/span&gt;&lt;span style="color: magenta;"&gt;tiburón&lt;/span&gt;&lt;span style="color: magenta;"&gt;"&lt;/span&gt; ] );&lt;br /&gt;&lt;span style="color: brown;"&gt; 6 &lt;/span&gt;&lt;span style="color: brown;"&gt;&lt;b&gt;do&lt;/b&gt;&lt;/span&gt; {&lt;br /&gt;&lt;span style="color: brown;"&gt; 7 &lt;/span&gt;    {&lt;br /&gt;&lt;span style="color: brown;"&gt; 8 &lt;/span&gt;        &lt;span style="color: darkcyan;"&gt;$v&lt;/span&gt; = a(&lt;span style="color: darkcyan;"&gt;$q&lt;/span&gt;);&lt;br /&gt;&lt;span style="color: brown;"&gt; 9 &lt;/span&gt;        &lt;span style="color: darkcyan;"&gt;$a&lt;/span&gt; = &lt;span style="color: darkcyan;"&gt;$t{$q}[$v]&lt;/span&gt;;&lt;br /&gt;&lt;span style="color: brown;"&gt;10 &lt;/span&gt;        &lt;span style="color: darkcyan;"&gt;$q&lt;/span&gt; = &lt;span style="color: darkcyan;"&gt;$a&lt;/span&gt;, &lt;span style="color: brown;"&gt;&lt;b&gt;redo&lt;/b&gt;&lt;/span&gt; &lt;span style="color: brown;"&gt;&lt;b&gt;if&lt;/b&gt;&lt;/span&gt; &lt;span style="color: darkcyan;"&gt;$t{$a}&lt;/span&gt;;&lt;br /&gt;&lt;span style="color: brown;"&gt;11 &lt;/span&gt;        &lt;span style="color: darkcyan;"&gt;$q&lt;/span&gt; = &lt;span style="color: darkcyan;"&gt;$s&lt;/span&gt;, &lt;span style="color: brown;"&gt;&lt;b&gt;next&lt;/b&gt;&lt;/span&gt; &lt;span style="color: brown;"&gt;&lt;b&gt;if&lt;/b&gt;&lt;/span&gt; a(&lt;span style="color: magenta;"&gt;"&lt;/span&gt;&lt;span style="color: magenta;"&gt;Es un(a) &lt;/span&gt;&lt;span style="color: darkcyan;"&gt;$a&lt;/span&gt;&lt;span style="color: magenta;"&gt;"&lt;/span&gt;);&lt;br /&gt;&lt;span style="color: brown;"&gt;12 &lt;/span&gt;        &lt;span style="color: darkcyan;"&gt;$n&lt;/span&gt; = p(&lt;span style="color: magenta;"&gt;"&lt;/span&gt;&lt;span style="color: magenta;"&gt;Nombre del animal: &lt;/span&gt;&lt;span style="color: magenta;"&gt;"&lt;/span&gt;);&lt;br /&gt;&lt;span style="color: brown;"&gt;13 &lt;/span&gt;        &lt;span style="color: darkcyan;"&gt;$o&lt;/span&gt; = p(&lt;span style="color: magenta;"&gt;"&lt;/span&gt;&lt;span style="color: magenta;"&gt;Una pregunta cierta para &lt;/span&gt;&lt;span style="color: darkcyan;"&gt;$n&lt;/span&gt;&lt;span style="color: magenta;"&gt; pero falsa para &lt;/span&gt;&lt;span style="color: darkcyan;"&gt;$a&lt;/span&gt;&lt;span style="color: magenta;"&gt;: &lt;/span&gt;&lt;span style="color: magenta;"&gt;"&lt;/span&gt;);&lt;br /&gt;&lt;span style="color: brown;"&gt;14 &lt;/span&gt;        &lt;span style="color: darkcyan;"&gt;$t{$o}&lt;/span&gt; = [ &lt;span style="color: darkcyan;"&gt;$t{$q}[$v]&lt;/span&gt;, &lt;span style="color: darkcyan;"&gt;$n&lt;/span&gt; ];&lt;br /&gt;&lt;span style="color: brown;"&gt;15 &lt;/span&gt;        &lt;span style="color: darkcyan;"&gt;$t{$q}[$v]&lt;/span&gt; = &lt;span style="color: darkcyan;"&gt;$o&lt;/span&gt;;&lt;br /&gt;&lt;span style="color: brown;"&gt;16 &lt;/span&gt;        &lt;span style="color: darkcyan;"&gt;$q&lt;/span&gt; = &lt;span style="color: darkcyan;"&gt;$s&lt;/span&gt;&lt;br /&gt;&lt;span style="color: brown;"&gt;17 &lt;/span&gt;    }&lt;br /&gt;&lt;span style="color: brown;"&gt;18 &lt;/span&gt;} &lt;span style="color: brown;"&gt;&lt;b&gt;while&lt;/b&gt;&lt;/span&gt; a(&lt;span style="color: magenta;"&gt;"&lt;/span&gt;&lt;span style="color: magenta;"&gt;Quieres jugar de nuevo&lt;/span&gt;&lt;span style="color: magenta;"&gt;"&lt;/span&gt;);&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;Los nombres en las variables son inútiles, los ciclos son difíciles de seguir y la estructura de datos que se utiliza utiliza trucos muy "inteligentes", que además no funcionan correctamente en algunos casos poco usuales, esto fue típico de alguna época, en las que las soluciones rápidas y sucias fueron mas la norma que la excepción.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;h2&gt;Procedimientos y DSL&lt;/h2&gt;&lt;br /&gt;En este estilo se usan mucho los prototipos convirtiendo cada subrutina en operadores que a veces son difíciles de seguir. Los objetos se utilizan mediante la sintaxis indirecta que trae algunos problemas de ambigüedad.&lt;br /&gt;&lt;br /&gt;Estilo 4: Procedimientos y DSL&lt;br /&gt;&lt;pre&gt;&lt;span style="color: brown;"&gt; 1 &lt;/span&gt;&lt;span style="color: #a020f0;"&gt;#!/usr/bin/env perl&lt;/span&gt;&lt;br /&gt;&lt;span style="color: brown;"&gt; 2 &lt;/span&gt;&lt;span style="color: #a020f0;"&gt;use &lt;/span&gt;Term::ReadLine;&lt;br /&gt;&lt;span style="color: brown;"&gt; 3 &lt;/span&gt;&lt;br /&gt;&lt;span style="color: brown;"&gt; 4 &lt;/span&gt;&lt;span style="color: #a020f0;"&gt;use strict&lt;/span&gt;;&lt;br /&gt;&lt;span style="color: brown;"&gt; 5 &lt;/span&gt;&lt;br /&gt;&lt;span style="color: brown;"&gt; 6 &lt;/span&gt;&lt;span style="color: brown;"&gt;&lt;b&gt;my&lt;/b&gt;&lt;/span&gt; &lt;span style="color: darkcyan;"&gt;$term&lt;/span&gt; = &lt;span style="color: brown;"&gt;&lt;b&gt;new&lt;/b&gt;&lt;/span&gt; Term::ReadLine &lt;span style="color: magenta;"&gt;"&lt;/span&gt;&lt;span style="color: magenta;"&gt;El juego de los animales&lt;/span&gt;&lt;span style="color: magenta;"&gt;"&lt;/span&gt;;&lt;br /&gt;&lt;span style="color: brown;"&gt; 7 &lt;/span&gt;&lt;br /&gt;&lt;span style="color: brown;"&gt; 8 &lt;/span&gt;&lt;span style="color: brown;"&gt;&lt;b&gt;sub&lt;/b&gt;&lt;/span&gt;&lt;span style="color: darkcyan;"&gt; &lt;/span&gt;&lt;span style="color: darkcyan;"&gt;prompt(&lt;/span&gt;&lt;span style="color: darkcyan;"&gt;$) &lt;/span&gt;{ &lt;span style="color: darkcyan;"&gt;$term&lt;/span&gt;&lt;span style="color: darkcyan;"&gt;-&amp;gt;readline&lt;/span&gt;(&lt;span style="color: brown;"&gt;&lt;b&gt;shift&lt;/b&gt;&lt;/span&gt;) }&lt;br /&gt;&lt;span style="color: brown;"&gt; 9 &lt;/span&gt;&lt;br /&gt;&lt;span style="color: brown;"&gt;10 &lt;/span&gt;&lt;span style="color: brown;"&gt;&lt;b&gt;sub&lt;/b&gt;&lt;/span&gt;&lt;span style="color: darkcyan;"&gt; &lt;/span&gt;&lt;span style="color: darkcyan;"&gt;si(&lt;/span&gt;&lt;span style="color: darkcyan;"&gt;$) &lt;/span&gt;{&lt;br /&gt;&lt;span style="color: brown;"&gt;11 &lt;/span&gt;    &lt;span style="color: brown;"&gt;&lt;b&gt;my&lt;/b&gt;&lt;/span&gt; &lt;span style="color: darkcyan;"&gt;$prompt&lt;/span&gt; = &lt;span style="color: brown;"&gt;&lt;b&gt;shift&lt;/b&gt;&lt;/span&gt;;&lt;br /&gt;&lt;span style="color: brown;"&gt;12 &lt;/span&gt;    &lt;span style="color: brown;"&gt;&lt;b&gt;while&lt;/b&gt;&lt;/span&gt; ( &lt;span style="color: brown;"&gt;&lt;b&gt;my&lt;/b&gt;&lt;/span&gt; &lt;span style="color: darkcyan;"&gt;$answer&lt;/span&gt; = prompt &lt;span style="color: magenta;"&gt;"&lt;/span&gt;&lt;span style="color: darkcyan;"&gt;$prompt&lt;/span&gt;&lt;span style="color: magenta;"&gt;? (s/n): &lt;/span&gt;&lt;span style="color: magenta;"&gt;"&lt;/span&gt; ) {&lt;br /&gt;&lt;span style="color: brown;"&gt;13 &lt;/span&gt;        &lt;span style="color: brown;"&gt;&lt;b&gt;return&lt;/b&gt;&lt;/span&gt; &lt;span style="color: darkcyan;"&gt;$answer&lt;/span&gt; =~&lt;span style="color: brown;"&gt;&lt;b&gt; /&lt;/b&gt;&lt;/span&gt;&lt;span style="color: magenta;"&gt;^&lt;/span&gt;&lt;span style="color: slateblue;"&gt;\s&lt;/span&gt;&lt;span style="color: slateblue;"&gt;*((&lt;/span&gt;&lt;span style="color: magenta;"&gt;si|s&lt;/span&gt;&lt;span style="color: slateblue;"&gt;)&lt;/span&gt;&lt;span style="color: magenta;"&gt;|&lt;/span&gt;&lt;span style="color: slateblue;"&gt;(&lt;/span&gt;&lt;span style="color: magenta;"&gt;no|n&lt;/span&gt;&lt;span style="color: slateblue;"&gt;))&lt;/span&gt;&lt;span style="color: slateblue;"&gt;\s&lt;/span&gt;&lt;span style="color: slateblue;"&gt;*&lt;/span&gt;&lt;span style="color: brown;"&gt;&lt;b&gt;/i&lt;/b&gt;&lt;/span&gt;;&lt;br /&gt;&lt;span style="color: brown;"&gt;14 &lt;/span&gt;        &lt;span style="color: brown;"&gt;&lt;b&gt;print&lt;/b&gt;&lt;/span&gt; { &lt;span style="color: darkcyan;"&gt;$term&lt;/span&gt;&lt;span style="color: darkcyan;"&gt;-&amp;gt;OUT&lt;/span&gt; } &lt;span style="color: magenta;"&gt;"&lt;/span&gt;&lt;span style="color: magenta;"&gt;Por favor responda 's' o 'n'&lt;/span&gt;&lt;span style="color: slateblue;"&gt;\n&lt;/span&gt;&lt;span style="color: magenta;"&gt;"&lt;/span&gt;;&lt;br /&gt;&lt;span style="color: brown;"&gt;15 &lt;/span&gt;    }&lt;br /&gt;&lt;span style="color: brown;"&gt;16 &lt;/span&gt;}&lt;br /&gt;&lt;span style="color: brown;"&gt;17 &lt;/span&gt;&lt;br /&gt;&lt;span style="color: brown;"&gt;18 &lt;/span&gt;&lt;span style="color: brown;"&gt;&lt;b&gt;sub&lt;/b&gt;&lt;/span&gt;&lt;span style="color: darkcyan;"&gt; &lt;/span&gt;&lt;span style="color: darkcyan;"&gt;play &lt;/span&gt;{&lt;br /&gt;&lt;span style="color: brown;"&gt;19 &lt;/span&gt;    &lt;span style="color: brown;"&gt;&lt;b&gt;my&lt;/b&gt;&lt;/span&gt; &lt;span style="color: darkcyan;"&gt;$guess&lt;/span&gt; = &lt;span style="color: brown;"&gt;&lt;b&gt;shift&lt;/b&gt;&lt;/span&gt;;&lt;br /&gt;&lt;span style="color: brown;"&gt;20 &lt;/span&gt;    &lt;span style="color: brown;"&gt;&lt;b&gt;my&lt;/b&gt;&lt;/span&gt; (&lt;span style="color: darkcyan;"&gt;$node&lt;/span&gt;, &lt;span style="color: darkcyan;"&gt;$branch&lt;/span&gt;);&lt;br /&gt;&lt;span style="color: brown;"&gt;21 &lt;/span&gt;    &lt;span style="color: brown;"&gt;&lt;b&gt;while&lt;/b&gt;&lt;/span&gt; ( &lt;span style="color: brown;"&gt;&lt;b&gt;ref&lt;/b&gt;&lt;/span&gt; &lt;span style="color: darkcyan;"&gt;$guess&lt;/span&gt; ) {&lt;br /&gt;&lt;span style="color: brown;"&gt;22 &lt;/span&gt;        &lt;span style="color: darkcyan;"&gt;$node&lt;/span&gt; = &lt;span style="color: darkcyan;"&gt;$guess&lt;/span&gt;;&lt;br /&gt;&lt;span style="color: brown;"&gt;23 &lt;/span&gt;        &lt;span style="color: darkcyan;"&gt;$branch&lt;/span&gt; = si &lt;span style="color: darkcyan;"&gt;$node&lt;/span&gt;&lt;span style="color: darkcyan;"&gt;-&amp;gt;{&lt;/span&gt;&lt;span style="color: magenta;"&gt;pregunta&lt;/span&gt;&lt;span style="color: darkcyan;"&gt;}&lt;/span&gt;;&lt;br /&gt;&lt;span style="color: brown;"&gt;24 &lt;/span&gt;        &lt;span style="color: darkcyan;"&gt;$guess&lt;/span&gt; = &lt;span style="color: darkcyan;"&gt;$node&lt;/span&gt;&lt;span style="color: darkcyan;"&gt;-&amp;gt;{&lt;/span&gt;&lt;span style="color: magenta;"&gt;ramas&lt;/span&gt;&lt;span style="color: darkcyan;"&gt;}&lt;/span&gt;&lt;span style="color: darkcyan;"&gt;[$branch]&lt;/span&gt;;&lt;br /&gt;&lt;span style="color: brown;"&gt;25 &lt;/span&gt;    }&lt;br /&gt;&lt;span style="color: brown;"&gt;26 &lt;/span&gt;    &lt;span style="color: brown;"&gt;&lt;b&gt;return&lt;/b&gt;&lt;/span&gt; &lt;span style="color: brown;"&gt;&lt;b&gt;if&lt;/b&gt;&lt;/span&gt; si &lt;span style="color: magenta;"&gt;"&lt;/span&gt;&lt;span style="color: magenta;"&gt;Es un(a) &lt;/span&gt;&lt;span style="color: darkcyan;"&gt;$guess&lt;/span&gt;&lt;span style="color: magenta;"&gt;"&lt;/span&gt;;&lt;br /&gt;&lt;span style="color: brown;"&gt;27 &lt;/span&gt;    &lt;span style="color: brown;"&gt;&lt;b&gt;my&lt;/b&gt;&lt;/span&gt; &lt;span style="color: darkcyan;"&gt;$animal&lt;/span&gt; = prompt &lt;span style="color: magenta;"&gt;"&lt;/span&gt;&lt;span style="color: magenta;"&gt;Nombre del animal: &lt;/span&gt;&lt;span style="color: magenta;"&gt;"&lt;/span&gt;;&lt;br /&gt;&lt;span style="color: brown;"&gt;28 &lt;/span&gt;    &lt;span style="color: brown;"&gt;&lt;b&gt;my&lt;/b&gt;&lt;/span&gt; &lt;span style="color: darkcyan;"&gt;$diff&lt;/span&gt;   = prompt &lt;span style="color: magenta;"&gt;"&lt;/span&gt;&lt;span style="color: magenta;"&gt;Una pregunta cierta para &lt;/span&gt;&lt;span style="color: darkcyan;"&gt;$animal&lt;/span&gt;&lt;span style="color: magenta;"&gt;"&lt;/span&gt; .&lt;br /&gt;&lt;span style="color: brown;"&gt;29 &lt;/span&gt;                        &lt;span style="color: magenta;"&gt;"&lt;/span&gt;&lt;span style="color: magenta;"&gt; pero falsa para &lt;/span&gt;&lt;span style="color: darkcyan;"&gt;$guess&lt;/span&gt;&lt;span style="color: magenta;"&gt;: &lt;/span&gt;&lt;span style="color: magenta;"&gt;"&lt;/span&gt;;&lt;br /&gt;&lt;span style="color: brown;"&gt;30 &lt;/span&gt;    &lt;span style="color: darkcyan;"&gt;$node&lt;/span&gt;&lt;span style="color: darkcyan;"&gt;-&amp;gt;{&lt;/span&gt;&lt;span style="color: magenta;"&gt;ramas&lt;/span&gt;&lt;span style="color: darkcyan;"&gt;}&lt;/span&gt;&lt;span style="color: darkcyan;"&gt;[$branch]&lt;/span&gt; = { &lt;span style="color: magenta;"&gt;pregunta &lt;/span&gt;=&amp;gt; &lt;span style="color: darkcyan;"&gt;$diff&lt;/span&gt;, &lt;span style="color: magenta;"&gt;ramas &lt;/span&gt;=&amp;gt; [ &lt;span style="color: darkcyan;"&gt;$guess&lt;/span&gt;, &lt;span style="color: darkcyan;"&gt;$animal&lt;/span&gt; ] };&lt;br /&gt;&lt;span style="color: brown;"&gt;31 &lt;/span&gt;}&lt;br /&gt;&lt;span style="color: brown;"&gt;32 &lt;/span&gt;&lt;br /&gt;&lt;span style="color: brown;"&gt;33 &lt;/span&gt;&lt;span style="color: brown;"&gt;&lt;b&gt;my&lt;/b&gt;&lt;/span&gt; &lt;span style="color: darkcyan;"&gt;$tree&lt;/span&gt; = { &lt;span style="color: magenta;"&gt;pregunta &lt;/span&gt;=&amp;gt; &lt;span style="color: magenta;"&gt;'&lt;/span&gt;&lt;span style="color: magenta;"&gt;vive en el agua&lt;/span&gt;&lt;span style="color: magenta;"&gt;'&lt;/span&gt;, &lt;span style="color: magenta;"&gt;ramas &lt;/span&gt;=&amp;gt; [ &lt;span style="color: magenta;"&gt;'&lt;/span&gt;&lt;span style="color: magenta;"&gt;tigre&lt;/span&gt;&lt;span style="color: magenta;"&gt;'&lt;/span&gt;, &lt;span style="color: magenta;"&gt;'&lt;/span&gt;&lt;span style="color: magenta;"&gt;tiburón&lt;/span&gt;&lt;span style="color: magenta;"&gt;'&lt;/span&gt; ] };&lt;br /&gt;&lt;span style="color: brown;"&gt;34 &lt;/span&gt;play &lt;span style="color: darkcyan;"&gt;$tree&lt;/span&gt;;&lt;br /&gt;&lt;span style="color: brown;"&gt;35 &lt;/span&gt;play &lt;span style="color: darkcyan;"&gt;$tree&lt;/span&gt; &lt;span style="color: brown;"&gt;&lt;b&gt;while&lt;/b&gt;&lt;/span&gt; si &lt;span style="color: magenta;"&gt;"&lt;/span&gt;&lt;span style="color: magenta;"&gt;Quieres jugar de nuevo&lt;/span&gt;&lt;span style="color: magenta;"&gt;"&lt;/span&gt;;&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;No es que esto este del todo mal, en efecto usar los prototipos permite hacer extender Perl como lo hace Moose, usando el azúcar sintáctico que proveen las subrutinas en Perl.&lt;br /&gt;&lt;br /&gt;Una característica interesante de este nuevo programa es una lógica mejor organizada y una estructura de datos mucho más fácil de comprender, sin embargo todavía usa algunas cosas inteligentes, como el acceso a las ramas utilizando el resultado de la comparación en la subrutina si() que retorna 1 en caso de ser cierto, pero undef en caso contrario, claro que Perl convierte undef en "" o en 0 según el contexto en que se use, pero no es una buena práctica andar haciendo eso por todos lados.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;h2&gt;Clases hechas a mano&lt;/h2&gt;&lt;br /&gt;Los objetos en Perl como en cualquier otro lenguaje trajeron las ventajas del encapsulamiento, consistencia y el reuso del código, sin embargo, para obtener todas las ventajas de este tipo de programación había que hacer métodos (subrutinas) que controlaran el acceso a los atributos. Hacer esto en Perl era laborioso, repetitivo y muy muy aburrido:&lt;br /&gt;&lt;br /&gt;Estilo 5: Objetos hechos a mano&lt;br /&gt;&lt;pre&gt;&lt;span style="color: brown;"&gt; 1 &lt;/span&gt;&lt;span style="color: brown;"&gt;&lt;b&gt;package&lt;/b&gt;&lt;/span&gt;&lt;span style="color: seagreen;"&gt;&lt;b&gt; QuestionNode;&lt;/b&gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="color: brown;"&gt; 2 &lt;/span&gt;&lt;span style="color: #a020f0;"&gt;use &lt;/span&gt;Carp;&lt;br /&gt;&lt;span style="color: brown;"&gt; 3 &lt;/span&gt;&lt;span style="color: #a020f0;"&gt;use strict&lt;/span&gt;;&lt;br /&gt;&lt;span style="color: brown;"&gt; 4 &lt;/span&gt;&lt;br /&gt;&lt;span style="color: brown;"&gt; 5 &lt;/span&gt;&lt;span style="color: brown;"&gt;&lt;b&gt;sub&lt;/b&gt;&lt;/span&gt;&lt;span style="color: darkcyan;"&gt; &lt;/span&gt;&lt;span style="color: darkcyan;"&gt;new &lt;/span&gt;{&lt;br /&gt;&lt;span style="color: brown;"&gt; 6 &lt;/span&gt;    &lt;span style="color: brown;"&gt;&lt;b&gt;my&lt;/b&gt;&lt;/span&gt; ( &lt;span style="color: darkcyan;"&gt;$class&lt;/span&gt;, &lt;span style="color: darkcyan;"&gt;$pregunta&lt;/span&gt;, &lt;span style="color: darkcyan;"&gt;$no&lt;/span&gt;, &lt;span style="color: darkcyan;"&gt;$si&lt;/span&gt; ) = &lt;span style="color: darkcyan;"&gt;@_&lt;/span&gt;;&lt;br /&gt;&lt;span style="color: brown;"&gt; 7 &lt;/span&gt;    &lt;span style="color: brown;"&gt;&lt;b&gt;bless&lt;/b&gt;&lt;/span&gt; { &lt;span style="color: magenta;"&gt;pregunta &lt;/span&gt;=&amp;gt; &lt;span style="color: darkcyan;"&gt;$pregunta&lt;/span&gt;, &lt;span style="color: magenta;"&gt;no &lt;/span&gt;=&amp;gt; &lt;span style="color: darkcyan;"&gt;$no&lt;/span&gt;, &lt;span style="color: magenta;"&gt;si &lt;/span&gt;=&amp;gt; &lt;span style="color: darkcyan;"&gt;$si&lt;/span&gt; }, &lt;span style="color: brown;"&gt;&lt;b&gt;ref&lt;/b&gt;&lt;/span&gt; &lt;span style="color: darkcyan;"&gt;$class&lt;/span&gt; || &lt;span style="color: darkcyan;"&gt;$class&lt;/span&gt;;&lt;br /&gt;&lt;span style="color: brown;"&gt; 8 &lt;/span&gt;}&lt;br /&gt;&lt;span style="color: brown;"&gt; 9 &lt;/span&gt;&lt;br /&gt;&lt;span style="color: brown;"&gt;10 &lt;/span&gt;&lt;span style="color: brown;"&gt;&lt;b&gt;sub&lt;/b&gt;&lt;/span&gt;&lt;span style="color: darkcyan;"&gt; &lt;/span&gt;&lt;span style="color: darkcyan;"&gt;pregunta &lt;/span&gt;{&lt;br /&gt;&lt;span style="color: brown;"&gt;11 &lt;/span&gt;    &lt;span style="color: brown;"&gt;&lt;b&gt;my&lt;/b&gt;&lt;/span&gt; &lt;span style="color: darkcyan;"&gt;$self&lt;/span&gt; = &lt;span style="color: brown;"&gt;&lt;b&gt;shift&lt;/b&gt;&lt;/span&gt;;&lt;br /&gt;&lt;span style="color: brown;"&gt;12 &lt;/span&gt;    &lt;span style="color: brown;"&gt;&lt;b&gt;return&lt;/b&gt;&lt;/span&gt; &lt;span style="color: darkcyan;"&gt;$self&lt;/span&gt;&lt;span style="color: darkcyan;"&gt;-&amp;gt;{&lt;/span&gt;&lt;span style="color: magenta;"&gt;pregunta&lt;/span&gt;&lt;span style="color: darkcyan;"&gt;}&lt;/span&gt; &lt;span style="color: brown;"&gt;&lt;b&gt;unless&lt;/b&gt;&lt;/span&gt; &lt;span style="color: darkcyan;"&gt;@_&lt;/span&gt;;&lt;br /&gt;&lt;span style="color: brown;"&gt;13 &lt;/span&gt;    croak &lt;span style="color: magenta;"&gt;"&lt;/span&gt;&lt;span style="color: magenta;"&gt;pregunta es un atributo de solo lectura&lt;/span&gt;&lt;span style="color: magenta;"&gt;"&lt;/span&gt;;&lt;br /&gt;&lt;span style="color: brown;"&gt;14 &lt;/span&gt;}&lt;br /&gt;&lt;span style="color: brown;"&gt;15 &lt;/span&gt;&lt;br /&gt;&lt;span style="color: brown;"&gt;16 &lt;/span&gt;&lt;span style="color: brown;"&gt;&lt;b&gt;sub&lt;/b&gt;&lt;/span&gt;&lt;span style="color: darkcyan;"&gt; &lt;/span&gt;&lt;span style="color: darkcyan;"&gt;si &lt;/span&gt;{&lt;br /&gt;&lt;span style="color: brown;"&gt;17 &lt;/span&gt;    &lt;span style="color: brown;"&gt;&lt;b&gt;my&lt;/b&gt;&lt;/span&gt; &lt;span style="color: darkcyan;"&gt;$self&lt;/span&gt; = &lt;span style="color: brown;"&gt;&lt;b&gt;shift&lt;/b&gt;&lt;/span&gt;;&lt;br /&gt;&lt;span style="color: brown;"&gt;18 &lt;/span&gt;    &lt;span style="color: brown;"&gt;&lt;b&gt;return&lt;/b&gt;&lt;/span&gt; &lt;span style="color: darkcyan;"&gt;$self&lt;/span&gt;&lt;span style="color: darkcyan;"&gt;-&amp;gt;{&lt;/span&gt;&lt;span style="color: magenta;"&gt;si&lt;/span&gt;&lt;span style="color: darkcyan;"&gt;}&lt;/span&gt; &lt;span style="color: brown;"&gt;&lt;b&gt;unless&lt;/b&gt;&lt;/span&gt; &lt;span style="color: darkcyan;"&gt;@_&lt;/span&gt;;&lt;br /&gt;&lt;span style="color: brown;"&gt;19 &lt;/span&gt;    &lt;span style="color: brown;"&gt;&lt;b&gt;return&lt;/b&gt;&lt;/span&gt; &lt;span style="color: darkcyan;"&gt;$self&lt;/span&gt;&lt;span style="color: darkcyan;"&gt;-&amp;gt;{&lt;/span&gt;&lt;span style="color: magenta;"&gt;si&lt;/span&gt;&lt;span style="color: darkcyan;"&gt;}&lt;/span&gt; = &lt;span style="color: brown;"&gt;&lt;b&gt;shift&lt;/b&gt;&lt;/span&gt;;&lt;br /&gt;&lt;span style="color: brown;"&gt;20 &lt;/span&gt;}&lt;br /&gt;&lt;span style="color: brown;"&gt;21 &lt;/span&gt;&lt;br /&gt;&lt;span style="color: brown;"&gt;22 &lt;/span&gt;&lt;span style="color: brown;"&gt;&lt;b&gt;sub&lt;/b&gt;&lt;/span&gt;&lt;span style="color: darkcyan;"&gt; &lt;/span&gt;&lt;span style="color: darkcyan;"&gt;no &lt;/span&gt;{&lt;br /&gt;&lt;span style="color: brown;"&gt;23 &lt;/span&gt;    &lt;span style="color: brown;"&gt;&lt;b&gt;my&lt;/b&gt;&lt;/span&gt; &lt;span style="color: darkcyan;"&gt;$self&lt;/span&gt; = &lt;span style="color: brown;"&gt;&lt;b&gt;shift&lt;/b&gt;&lt;/span&gt;;&lt;br /&gt;&lt;span style="color: brown;"&gt;24 &lt;/span&gt;    &lt;span style="color: brown;"&gt;&lt;b&gt;return&lt;/b&gt;&lt;/span&gt; &lt;span style="color: darkcyan;"&gt;$self&lt;/span&gt;&lt;span style="color: darkcyan;"&gt;-&amp;gt;{&lt;/span&gt;&lt;span style="color: magenta;"&gt;no&lt;/span&gt;&lt;span style="color: darkcyan;"&gt;}&lt;/span&gt; &lt;span style="color: brown;"&gt;&lt;b&gt;unless&lt;/b&gt;&lt;/span&gt; &lt;span style="color: darkcyan;"&gt;@_&lt;/span&gt;;&lt;br /&gt;&lt;span style="color: brown;"&gt;25 &lt;/span&gt;    &lt;span style="color: brown;"&gt;&lt;b&gt;return&lt;/b&gt;&lt;/span&gt; &lt;span style="color: darkcyan;"&gt;$self&lt;/span&gt;&lt;span style="color: darkcyan;"&gt;-&amp;gt;{&lt;/span&gt;&lt;span style="color: magenta;"&gt;no&lt;/span&gt;&lt;span style="color: darkcyan;"&gt;}&lt;/span&gt; = &lt;span style="color: brown;"&gt;&lt;b&gt;shift&lt;/b&gt;&lt;/span&gt;;&lt;br /&gt;&lt;span style="color: brown;"&gt;26 &lt;/span&gt;}&lt;br /&gt;&lt;span style="color: brown;"&gt;27 &lt;/span&gt;&lt;br /&gt;&lt;span style="color: brown;"&gt;28 &lt;/span&gt;&lt;span style="color: magenta;"&gt;1&lt;/span&gt;;&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;pre&gt;&lt;span style="color: brown;"&gt; 1 &lt;/span&gt;&lt;span style="color: #a020f0;"&gt;#!/usr/bin/env perl&lt;/span&gt;&lt;br /&gt;&lt;span style="color: brown;"&gt; 2 &lt;/span&gt;&lt;span style="color: #a020f0;"&gt;use &lt;/span&gt;QuestionNode;&lt;br /&gt;&lt;span style="color: brown;"&gt; 3 &lt;/span&gt;&lt;span style="color: #a020f0;"&gt;use &lt;/span&gt;Term::ReadLine;&lt;br /&gt;&lt;span style="color: brown;"&gt; 4 &lt;/span&gt;&lt;span style="color: #a020f0;"&gt;use &lt;/span&gt;IO::Handle;&lt;br /&gt;&lt;span style="color: brown;"&gt; 5 &lt;/span&gt;&lt;br /&gt;&lt;span style="color: brown;"&gt; 6 &lt;/span&gt;&lt;span style="color: #a020f0;"&gt;use strict&lt;/span&gt;;&lt;br /&gt;&lt;span style="color: brown;"&gt; 7 &lt;/span&gt;&lt;br /&gt;&lt;span style="color: brown;"&gt; 8 &lt;/span&gt;&lt;span style="color: brown;"&gt;&lt;b&gt;my&lt;/b&gt;&lt;/span&gt; &lt;span style="color: darkcyan;"&gt;$term&lt;/span&gt; = Term::ReadLine-&amp;gt;&lt;span style="color: brown;"&gt;&lt;b&gt;new&lt;/b&gt;&lt;/span&gt;(&lt;span style="color: magenta;"&gt;"&lt;/span&gt;&lt;span style="color: magenta;"&gt;El juego de los animales&lt;/span&gt;&lt;span style="color: magenta;"&gt;"&lt;/span&gt;);&lt;br /&gt;&lt;span style="color: brown;"&gt; 9 &lt;/span&gt;&lt;br /&gt;&lt;span style="color: brown;"&gt;10 &lt;/span&gt;&lt;span style="color: brown;"&gt;&lt;b&gt;sub&lt;/b&gt;&lt;/span&gt;&lt;span style="color: darkcyan;"&gt; &lt;/span&gt;&lt;span style="color: darkcyan;"&gt;prompt(&lt;/span&gt;&lt;span style="color: darkcyan;"&gt;$) &lt;/span&gt;{ &lt;span style="color: darkcyan;"&gt;$term&lt;/span&gt;&lt;span style="color: darkcyan;"&gt;-&amp;gt;readline&lt;/span&gt;(&lt;span style="color: brown;"&gt;&lt;b&gt;shift&lt;/b&gt;&lt;/span&gt;) }&lt;br /&gt;&lt;span style="color: brown;"&gt;11 &lt;/span&gt;&lt;br /&gt;&lt;span style="color: brown;"&gt;12 &lt;/span&gt;&lt;span style="color: brown;"&gt;&lt;b&gt;sub&lt;/b&gt;&lt;/span&gt;&lt;span style="color: darkcyan;"&gt; &lt;/span&gt;&lt;span style="color: darkcyan;"&gt;si(&lt;/span&gt;&lt;span style="color: darkcyan;"&gt;$) &lt;/span&gt;{&lt;br /&gt;&lt;span style="color: brown;"&gt;13 &lt;/span&gt;    &lt;span style="color: brown;"&gt;&lt;b&gt;my&lt;/b&gt;&lt;/span&gt; &lt;span style="color: darkcyan;"&gt;$prompt&lt;/span&gt; = &lt;span style="color: brown;"&gt;&lt;b&gt;shift&lt;/b&gt;&lt;/span&gt;;&lt;br /&gt;&lt;span style="color: brown;"&gt;14 &lt;/span&gt;    &lt;span style="color: brown;"&gt;&lt;b&gt;while&lt;/b&gt;&lt;/span&gt; (&lt;span style="color: magenta;"&gt;1&lt;/span&gt;) {&lt;br /&gt;&lt;span style="color: brown;"&gt;15 &lt;/span&gt;        &lt;span style="color: brown;"&gt;&lt;b&gt;my&lt;/b&gt;&lt;/span&gt; &lt;span style="color: darkcyan;"&gt;$answer&lt;/span&gt; = prompt(&lt;span style="color: magenta;"&gt;"&lt;/span&gt;&lt;span style="color: darkcyan;"&gt;$prompt&lt;/span&gt;&lt;span style="color: magenta;"&gt;? (y/n): &lt;/span&gt;&lt;span style="color: magenta;"&gt;"&lt;/span&gt;);&lt;br /&gt;&lt;span style="color: brown;"&gt;16 &lt;/span&gt;        &lt;span style="color: brown;"&gt;&lt;b&gt;return&lt;/b&gt;&lt;/span&gt; ( &lt;span style="color: darkcyan;"&gt;$2&lt;/span&gt; ? &lt;span style="color: magenta;"&gt;1&lt;/span&gt; : &lt;span style="color: magenta;"&gt;0&lt;/span&gt; ) &lt;span style="color: brown;"&gt;&lt;b&gt;if&lt;/b&gt;&lt;/span&gt; &lt;span style="color: darkcyan;"&gt;$answer&lt;/span&gt; =~&lt;span style="color: brown;"&gt;&lt;b&gt; /&lt;/b&gt;&lt;/span&gt;&lt;span style="color: magenta;"&gt;^&lt;/span&gt;&lt;span style="color: slateblue;"&gt;\s&lt;/span&gt;&lt;span style="color: slateblue;"&gt;*((&lt;/span&gt;&lt;span style="color: magenta;"&gt;si|s&lt;/span&gt;&lt;span style="color: slateblue;"&gt;)&lt;/span&gt;&lt;span style="color: magenta;"&gt;|&lt;/span&gt;&lt;span style="color: slateblue;"&gt;(&lt;/span&gt;&lt;span style="color: magenta;"&gt;no|n&lt;/span&gt;&lt;span style="color: slateblue;"&gt;))&lt;/span&gt;&lt;span style="color: slateblue;"&gt;\s&lt;/span&gt;&lt;span style="color: slateblue;"&gt;*&lt;/span&gt;&lt;span style="color: brown;"&gt;&lt;b&gt;/i&lt;/b&gt;&lt;/span&gt;;&lt;br /&gt;&lt;span style="color: brown;"&gt;17 &lt;/span&gt;        &lt;span style="color: darkcyan;"&gt;$term&lt;/span&gt;&lt;span style="color: darkcyan;"&gt;-&amp;gt;OUT&lt;/span&gt;-&amp;gt;&lt;span style="color: brown;"&gt;&lt;b&gt;print&lt;/b&gt;&lt;/span&gt;(&lt;span style="color: magenta;"&gt;"&lt;/span&gt;&lt;span style="color: magenta;"&gt;Responde 's' o 'n'&lt;/span&gt;&lt;span style="color: slateblue;"&gt;\n&lt;/span&gt;&lt;span style="color: magenta;"&gt;"&lt;/span&gt;);&lt;br /&gt;&lt;span style="color: brown;"&gt;18 &lt;/span&gt;    }&lt;br /&gt;&lt;span style="color: brown;"&gt;19 &lt;/span&gt;}&lt;br /&gt;&lt;span style="color: brown;"&gt;20 &lt;/span&gt;&lt;br /&gt;&lt;span style="color: brown;"&gt;21 &lt;/span&gt;&lt;span style="color: brown;"&gt;&lt;b&gt;sub&lt;/b&gt;&lt;/span&gt;&lt;span style="color: darkcyan;"&gt; &lt;/span&gt;&lt;span style="color: darkcyan;"&gt;play &lt;/span&gt;{&lt;br /&gt;&lt;span style="color: brown;"&gt;22 &lt;/span&gt;    &lt;span style="color: brown;"&gt;&lt;b&gt;my&lt;/b&gt;&lt;/span&gt; &lt;span style="color: darkcyan;"&gt;$guess&lt;/span&gt; = &lt;span style="color: brown;"&gt;&lt;b&gt;shift&lt;/b&gt;&lt;/span&gt;;&lt;br /&gt;&lt;span style="color: brown;"&gt;23 &lt;/span&gt;    &lt;span style="color: brown;"&gt;&lt;b&gt;my&lt;/b&gt;&lt;/span&gt; ( &lt;span style="color: darkcyan;"&gt;$node&lt;/span&gt;, &lt;span style="color: darkcyan;"&gt;$branch&lt;/span&gt; );&lt;br /&gt;&lt;span style="color: brown;"&gt;24 &lt;/span&gt;    &lt;span style="color: brown;"&gt;&lt;b&gt;while&lt;/b&gt;&lt;/span&gt; ( &lt;span style="color: brown;"&gt;&lt;b&gt;ref&lt;/b&gt;&lt;/span&gt; &lt;span style="color: darkcyan;"&gt;$guess&lt;/span&gt; ) {&lt;br /&gt;&lt;span style="color: brown;"&gt;25 &lt;/span&gt;        &lt;span style="color: darkcyan;"&gt;$node&lt;/span&gt;   = &lt;span style="color: darkcyan;"&gt;$guess&lt;/span&gt;;&lt;br /&gt;&lt;span style="color: brown;"&gt;26 &lt;/span&gt;        &lt;span style="color: darkcyan;"&gt;$branch&lt;/span&gt; = si &lt;span style="color: darkcyan;"&gt;$node&lt;/span&gt;&lt;span style="color: darkcyan;"&gt;-&amp;gt;pregunta&lt;/span&gt; ? &lt;span style="color: magenta;"&gt;"&lt;/span&gt;&lt;span style="color: magenta;"&gt;si&lt;/span&gt;&lt;span style="color: magenta;"&gt;"&lt;/span&gt; : &lt;span style="color: magenta;"&gt;"&lt;/span&gt;&lt;span style="color: magenta;"&gt;no&lt;/span&gt;&lt;span style="color: magenta;"&gt;"&lt;/span&gt;;&lt;br /&gt;&lt;span style="color: brown;"&gt;27 &lt;/span&gt;        &lt;span style="color: darkcyan;"&gt;$guess&lt;/span&gt;  = &lt;span style="color: darkcyan;"&gt;$node&lt;/span&gt;-&amp;gt;&lt;span style="color: darkcyan;"&gt;$branch&lt;/span&gt;;&lt;br /&gt;&lt;span style="color: brown;"&gt;28 &lt;/span&gt;    }&lt;br /&gt;&lt;span style="color: brown;"&gt;29 &lt;/span&gt;    &lt;span style="color: brown;"&gt;&lt;b&gt;return&lt;/b&gt;&lt;/span&gt; &lt;span style="color: brown;"&gt;&lt;b&gt;if&lt;/b&gt;&lt;/span&gt; si &lt;span style="color: magenta;"&gt;"&lt;/span&gt;&lt;span style="color: magenta;"&gt;Es un(a) &lt;/span&gt;&lt;span style="color: darkcyan;"&gt;$guess&lt;/span&gt;&lt;span style="color: magenta;"&gt;"&lt;/span&gt;;&lt;br /&gt;&lt;span style="color: brown;"&gt;30 &lt;/span&gt;    &lt;span style="color: brown;"&gt;&lt;b&gt;my&lt;/b&gt;&lt;/span&gt; &lt;span style="color: darkcyan;"&gt;$animal&lt;/span&gt; = prompt &lt;span style="color: magenta;"&gt;"&lt;/span&gt;&lt;span style="color: magenta;"&gt;Nombre del animal: &lt;/span&gt;&lt;span style="color: magenta;"&gt;"&lt;/span&gt;;&lt;br /&gt;&lt;span style="color: brown;"&gt;31 &lt;/span&gt;    &lt;span style="color: brown;"&gt;&lt;b&gt;my&lt;/b&gt;&lt;/span&gt; &lt;span style="color: darkcyan;"&gt;$diff&lt;/span&gt;   = prompt&lt;br /&gt;&lt;span style="color: brown;"&gt;32 &lt;/span&gt;        &lt;span style="color: magenta;"&gt;"&lt;/span&gt;&lt;span style="color: magenta;"&gt;Una pregunta cierta para &lt;/span&gt;&lt;span style="color: darkcyan;"&gt;$animal&lt;/span&gt;&lt;span style="color: magenta;"&gt; pero falsa para &lt;/span&gt;&lt;span style="color: darkcyan;"&gt;$guess&lt;/span&gt;&lt;span style="color: magenta;"&gt;: &lt;/span&gt;&lt;span style="color: magenta;"&gt;"&lt;/span&gt;;&lt;br /&gt;&lt;span style="color: brown;"&gt;33 &lt;/span&gt;    &lt;span style="color: darkcyan;"&gt;$node&lt;/span&gt;-&amp;gt;&lt;span style="color: darkcyan;"&gt;$branch&lt;/span&gt;( QuestionNode-&amp;gt;&lt;span style="color: brown;"&gt;&lt;b&gt;new&lt;/b&gt;&lt;/span&gt;( &lt;span style="color: darkcyan;"&gt;$diff&lt;/span&gt;, &lt;span style="color: darkcyan;"&gt;$guess&lt;/span&gt;, &lt;span style="color: darkcyan;"&gt;$animal&lt;/span&gt; ) );&lt;br /&gt;&lt;span style="color: brown;"&gt;34 &lt;/span&gt;}&lt;br /&gt;&lt;span style="color: brown;"&gt;35 &lt;/span&gt;&lt;br /&gt;&lt;span style="color: brown;"&gt;36 &lt;/span&gt;&lt;span style="color: brown;"&gt;&lt;b&gt;my&lt;/b&gt;&lt;/span&gt; &lt;span style="color: darkcyan;"&gt;$tree&lt;/span&gt; = &lt;span style="color: brown;"&gt;&lt;b&gt;new&lt;/b&gt;&lt;/span&gt; QuestionNode( &lt;span style="color: magenta;"&gt;'&lt;/span&gt;&lt;span style="color: magenta;"&gt;vive en el agua&lt;/span&gt;&lt;span style="color: magenta;"&gt;'&lt;/span&gt;, &lt;span style="color: magenta;"&gt;'&lt;/span&gt;&lt;span style="color: magenta;"&gt;tigre&lt;/span&gt;&lt;span style="color: magenta;"&gt;'&lt;/span&gt;, &lt;span style="color: magenta;"&gt;'&lt;/span&gt;&lt;span style="color: magenta;"&gt;tiburón&lt;/span&gt;&lt;span style="color: magenta;"&gt;'&lt;/span&gt; );&lt;br /&gt;&lt;span style="color: brown;"&gt;37 &lt;/span&gt;play &lt;span style="color: darkcyan;"&gt;$tree&lt;/span&gt;;&lt;br /&gt;&lt;span style="color: brown;"&gt;38 &lt;/span&gt;play &lt;span style="color: darkcyan;"&gt;$tree&lt;/span&gt; &lt;span style="color: brown;"&gt;&lt;b&gt;while&lt;/b&gt;&lt;/span&gt; si &lt;span style="color: magenta;"&gt;"&lt;/span&gt;&lt;span style="color: magenta;"&gt;Quieres jugar de nuevo&lt;/span&gt;&lt;span style="color: magenta;"&gt;"&lt;/span&gt;;&lt;br /&gt;&lt;span style="color: brown;"&gt;39 &lt;/span&gt;&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;En el ejemplo se siguen usando los prototipos y la sintaxis indirecta para algunas cosas y para otras no.&lt;br /&gt;&lt;br /&gt;Hacer los accessors en la clase QuestionNode era claramente una labor repetitiva y rápidamente la comunidad le buscó varias soluciones a este problema, que fueron agregadas al CPAN.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;h2&gt;Asistentes de Clases&lt;/h2&gt;&lt;br /&gt;En el CPAN florecieron muchas herramientas que facilitaban la programación orientada a objetos, desde pragmas como "fields" que verificaban las claves de un hash a tiempo de compilación hasta los objetos invertidos (inside-out) implementados por Class::Std que mejoraban la encapsulación.&lt;br /&gt;&lt;br /&gt;Yo fui un fanático de Class::Accessor (en realidad de Class::Accessor::Fast), y si hubiera hecho el programa en aquella época quedaría así:&lt;br /&gt;&lt;br /&gt;Estilo 6: Objetos asistidos&lt;br /&gt;&lt;br /&gt;game.pl:&lt;br /&gt;&lt;pre&gt;&lt;span style="color: brown;"&gt;1 &lt;/span&gt;&lt;span style="color: #a020f0;"&gt;#!/usr/bin/env perl&lt;/span&gt;&lt;br /&gt;&lt;span style="color: brown;"&gt;2 &lt;/span&gt;&lt;span style="color: #a020f0;"&gt;use &lt;/span&gt;AnimalsGame;&lt;br /&gt;&lt;span style="color: brown;"&gt;3 &lt;/span&gt;AnimalsGame-&amp;gt;&lt;span style="color: brown;"&gt;&lt;b&gt;new&lt;/b&gt;&lt;/span&gt;-&amp;gt;run;&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;QuestionNode.pm:&lt;br /&gt;&lt;pre&gt;&lt;span style="color: brown;"&gt;1 &lt;/span&gt;&lt;span style="color: brown;"&gt;&lt;b&gt;package&lt;/b&gt;&lt;/span&gt;&lt;span style="color: seagreen;"&gt;&lt;b&gt; QuestionNode;&lt;/b&gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="color: brown;"&gt;2 &lt;/span&gt;&lt;span style="color: #a020f0;"&gt;use base&lt;/span&gt; &lt;span style="color: magenta;"&gt;"&lt;/span&gt;&lt;span style="color: magenta;"&gt;Class::Accessor&lt;/span&gt;&lt;span style="color: magenta;"&gt;"&lt;/span&gt;;&lt;br /&gt;&lt;span style="color: brown;"&gt;3 &lt;/span&gt;&lt;span style="color: #a020f0;"&gt;use strict&lt;/span&gt;;&lt;br /&gt;&lt;span style="color: brown;"&gt;4 &lt;/span&gt;&lt;br /&gt;&lt;span style="color: brown;"&gt;5 &lt;/span&gt;__PACKAGE__-&amp;gt;mk_ro_accessors(&lt;span style="color: magenta;"&gt;"&lt;/span&gt;&lt;span style="color: magenta;"&gt;pregunta&lt;/span&gt;&lt;span style="color: magenta;"&gt;"&lt;/span&gt;);&lt;br /&gt;&lt;span style="color: brown;"&gt;6 &lt;/span&gt;__PACKAGE__-&amp;gt;mk_accessors(&lt;span style="color: magenta;"&gt;"&lt;/span&gt;&lt;span style="color: magenta;"&gt;si&lt;/span&gt;&lt;span style="color: magenta;"&gt;"&lt;/span&gt;, &lt;span style="color: magenta;"&gt;"&lt;/span&gt;&lt;span style="color: magenta;"&gt;no&lt;/span&gt;&lt;span style="color: magenta;"&gt;"&lt;/span&gt;);&lt;br /&gt;&lt;span style="color: brown;"&gt;7 &lt;/span&gt;&lt;br /&gt;&lt;span style="color: brown;"&gt;8 &lt;/span&gt;&lt;span style="color: magenta;"&gt;1&lt;/span&gt;;&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;AnimalsGame.pm:&lt;br /&gt;&lt;pre&gt;&lt;span style="color: brown;"&gt; 1 &lt;/span&gt;&lt;span style="color: brown;"&gt;&lt;b&gt;package&lt;/b&gt;&lt;/span&gt;&lt;span style="color: seagreen;"&gt;&lt;b&gt; AnimalsGame;&lt;/b&gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="color: brown;"&gt; 2 &lt;/span&gt;&lt;span style="color: #a020f0;"&gt;use &lt;/span&gt;QuestionNode;&lt;br /&gt;&lt;span style="color: brown;"&gt; 3 &lt;/span&gt;&lt;span style="color: #a020f0;"&gt;use &lt;/span&gt;Term::ReadLine;&lt;br /&gt;&lt;span style="color: brown;"&gt; 4 &lt;/span&gt;&lt;span style="color: #a020f0;"&gt;use &lt;/span&gt;IO::Handle;&lt;br /&gt;&lt;span style="color: brown;"&gt; 5 &lt;/span&gt;&lt;span style="color: #a020f0;"&gt;use base&lt;/span&gt; &lt;span style="color: magenta;"&gt;"&lt;/span&gt;&lt;span style="color: magenta;"&gt;Class::Accessor&lt;/span&gt;&lt;span style="color: magenta;"&gt;"&lt;/span&gt;;&lt;br /&gt;&lt;span style="color: brown;"&gt; 6 &lt;/span&gt;&lt;span style="color: #a020f0;"&gt;use strict&lt;/span&gt;;&lt;br /&gt;&lt;span style="color: brown;"&gt; 7 &lt;/span&gt;&lt;br /&gt;&lt;span style="color: brown;"&gt; 8 &lt;/span&gt;__PACKAGE__-&amp;gt;mk_ro_accessors(&lt;span style="color: magenta;"&gt;qw(&lt;/span&gt;&lt;span style="color: magenta;"&gt;tree term&lt;/span&gt;&lt;span style="color: magenta;"&gt;)&lt;/span&gt;);&lt;br /&gt;&lt;span style="color: brown;"&gt; 9 &lt;/span&gt;&lt;br /&gt;&lt;span style="color: brown;"&gt;10 &lt;/span&gt;&lt;span style="color: brown;"&gt;&lt;b&gt;sub&lt;/b&gt;&lt;/span&gt;&lt;span style="color: darkcyan;"&gt; &lt;/span&gt;&lt;span style="color: darkcyan;"&gt;prompt &lt;/span&gt;{&lt;br /&gt;&lt;span style="color: brown;"&gt;11 &lt;/span&gt;    &lt;span style="color: brown;"&gt;&lt;b&gt;my&lt;/b&gt;&lt;/span&gt; &lt;span style="color: darkcyan;"&gt;$self&lt;/span&gt; = &lt;span style="color: brown;"&gt;&lt;b&gt;shift&lt;/b&gt;&lt;/span&gt;;&lt;br /&gt;&lt;span style="color: brown;"&gt;12 &lt;/span&gt;    &lt;span style="color: darkcyan;"&gt;$self&lt;/span&gt;&lt;span style="color: darkcyan;"&gt;-&amp;gt;term&lt;/span&gt;-&amp;gt;&lt;span style="color: brown;"&gt;&lt;b&gt;readline&lt;/b&gt;&lt;/span&gt;(&lt;span style="color: brown;"&gt;&lt;b&gt;shift&lt;/b&gt;&lt;/span&gt;);&lt;br /&gt;&lt;span style="color: brown;"&gt;13 &lt;/span&gt;}&lt;br /&gt;&lt;span style="color: brown;"&gt;14 &lt;/span&gt;&lt;br /&gt;&lt;span style="color: brown;"&gt;15 &lt;/span&gt;&lt;span style="color: brown;"&gt;&lt;b&gt;sub&lt;/b&gt;&lt;/span&gt;&lt;span style="color: darkcyan;"&gt; &lt;/span&gt;&lt;span style="color: darkcyan;"&gt;si &lt;/span&gt;{&lt;br /&gt;&lt;span style="color: brown;"&gt;16 &lt;/span&gt;    &lt;span style="color: brown;"&gt;&lt;b&gt;my&lt;/b&gt;&lt;/span&gt; &lt;span style="color: darkcyan;"&gt;$self&lt;/span&gt;   = &lt;span style="color: brown;"&gt;&lt;b&gt;shift&lt;/b&gt;&lt;/span&gt;;&lt;br /&gt;&lt;span style="color: brown;"&gt;17 &lt;/span&gt;    &lt;span style="color: brown;"&gt;&lt;b&gt;my&lt;/b&gt;&lt;/span&gt; &lt;span style="color: darkcyan;"&gt;$prompt&lt;/span&gt; = &lt;span style="color: brown;"&gt;&lt;b&gt;shift&lt;/b&gt;&lt;/span&gt;;&lt;br /&gt;&lt;span style="color: brown;"&gt;18 &lt;/span&gt;    &lt;span style="color: brown;"&gt;&lt;b&gt;while&lt;/b&gt;&lt;/span&gt; (&lt;span style="color: magenta;"&gt;1&lt;/span&gt;) {&lt;br /&gt;&lt;span style="color: brown;"&gt;19 &lt;/span&gt;        &lt;span style="color: brown;"&gt;&lt;b&gt;my&lt;/b&gt;&lt;/span&gt; &lt;span style="color: darkcyan;"&gt;$answer&lt;/span&gt; = &lt;span style="color: darkcyan;"&gt;$self&lt;/span&gt;&lt;span style="color: darkcyan;"&gt;-&amp;gt;prompt&lt;/span&gt;(&lt;span style="color: magenta;"&gt;"&lt;/span&gt;&lt;span style="color: darkcyan;"&gt;$prompt&lt;/span&gt;&lt;span style="color: magenta;"&gt;? (y/n): &lt;/span&gt;&lt;span style="color: magenta;"&gt;"&lt;/span&gt;);&lt;br /&gt;&lt;span style="color: brown;"&gt;20 &lt;/span&gt;        &lt;span style="color: brown;"&gt;&lt;b&gt;return&lt;/b&gt;&lt;/span&gt; ( &lt;span style="color: darkcyan;"&gt;$2&lt;/span&gt; ? &lt;span style="color: magenta;"&gt;1&lt;/span&gt; : &lt;span style="color: magenta;"&gt;0&lt;/span&gt; ) &lt;span style="color: brown;"&gt;&lt;b&gt;if&lt;/b&gt;&lt;/span&gt; &lt;span style="color: darkcyan;"&gt;$answer&lt;/span&gt; =~&lt;span style="color: brown;"&gt;&lt;b&gt; /&lt;/b&gt;&lt;/span&gt;&lt;span style="color: magenta;"&gt;^&lt;/span&gt;&lt;span style="color: slateblue;"&gt;\s&lt;/span&gt;&lt;span style="color: slateblue;"&gt;*((&lt;/span&gt;&lt;span style="color: magenta;"&gt;si|s&lt;/span&gt;&lt;span style="color: slateblue;"&gt;)&lt;/span&gt;&lt;span style="color: magenta;"&gt;|&lt;/span&gt;&lt;span style="color: slateblue;"&gt;(&lt;/span&gt;&lt;span style="color: magenta;"&gt;no|n&lt;/span&gt;&lt;span style="color: slateblue;"&gt;))&lt;/span&gt;&lt;span style="color: slateblue;"&gt;\s&lt;/span&gt;&lt;span style="color: slateblue;"&gt;*&lt;/span&gt;&lt;span style="color: brown;"&gt;&lt;b&gt;/i&lt;/b&gt;&lt;/span&gt;;&lt;br /&gt;&lt;span style="color: brown;"&gt;21 &lt;/span&gt;        &lt;span style="color: darkcyan;"&gt;$self&lt;/span&gt;&lt;span style="color: darkcyan;"&gt;-&amp;gt;term&lt;/span&gt;-&amp;gt;OUT-&amp;gt;&lt;span style="color: brown;"&gt;&lt;b&gt;print&lt;/b&gt;&lt;/span&gt;(&lt;span style="color: magenta;"&gt;"&lt;/span&gt;&lt;span style="color: magenta;"&gt;Responde 's' o 'n'&lt;/span&gt;&lt;span style="color: slateblue;"&gt;\n&lt;/span&gt;&lt;span style="color: magenta;"&gt;"&lt;/span&gt;);&lt;br /&gt;&lt;span style="color: brown;"&gt;22 &lt;/span&gt;    }&lt;br /&gt;&lt;span style="color: brown;"&gt;23 &lt;/span&gt;}&lt;br /&gt;&lt;span style="color: brown;"&gt;24 &lt;/span&gt;&lt;br /&gt;&lt;span style="color: brown;"&gt;25 &lt;/span&gt;&lt;span style="color: brown;"&gt;&lt;b&gt;sub&lt;/b&gt;&lt;/span&gt;&lt;span style="color: darkcyan;"&gt; &lt;/span&gt;&lt;span style="color: darkcyan;"&gt;play &lt;/span&gt;{&lt;br /&gt;&lt;span style="color: brown;"&gt;26 &lt;/span&gt;    &lt;span style="color: brown;"&gt;&lt;b&gt;my&lt;/b&gt;&lt;/span&gt; &lt;span style="color: darkcyan;"&gt;$self&lt;/span&gt;  = &lt;span style="color: brown;"&gt;&lt;b&gt;shift&lt;/b&gt;&lt;/span&gt;;&lt;br /&gt;&lt;span style="color: brown;"&gt;27 &lt;/span&gt;    &lt;span style="color: brown;"&gt;&lt;b&gt;my&lt;/b&gt;&lt;/span&gt; &lt;span style="color: darkcyan;"&gt;$guess&lt;/span&gt; = &lt;span style="color: darkcyan;"&gt;$self&lt;/span&gt;&lt;span style="color: darkcyan;"&gt;-&amp;gt;tree&lt;/span&gt;;&lt;br /&gt;&lt;span style="color: brown;"&gt;28 &lt;/span&gt;    &lt;span style="color: brown;"&gt;&lt;b&gt;my&lt;/b&gt;&lt;/span&gt; ( &lt;span style="color: darkcyan;"&gt;$node&lt;/span&gt;, &lt;span style="color: darkcyan;"&gt;$branch&lt;/span&gt; );&lt;br /&gt;&lt;span style="color: brown;"&gt;29 &lt;/span&gt;    &lt;span style="color: brown;"&gt;&lt;b&gt;while&lt;/b&gt;&lt;/span&gt; ( &lt;span style="color: brown;"&gt;&lt;b&gt;ref&lt;/b&gt;&lt;/span&gt; &lt;span style="color: darkcyan;"&gt;$guess&lt;/span&gt; ) {&lt;br /&gt;&lt;span style="color: brown;"&gt;30 &lt;/span&gt;        &lt;span style="color: darkcyan;"&gt;$node&lt;/span&gt;   = &lt;span style="color: darkcyan;"&gt;$guess&lt;/span&gt;;&lt;br /&gt;&lt;span style="color: brown;"&gt;31 &lt;/span&gt;        &lt;span style="color: darkcyan;"&gt;$branch&lt;/span&gt; = &lt;span style="color: darkcyan;"&gt;$self&lt;/span&gt;&lt;span style="color: darkcyan;"&gt;-&amp;gt;si&lt;/span&gt;( &lt;span style="color: darkcyan;"&gt;$node&lt;/span&gt;&lt;span style="color: darkcyan;"&gt;-&amp;gt;pregunta&lt;/span&gt; ) ? &lt;span style="color: magenta;"&gt;"&lt;/span&gt;&lt;span style="color: magenta;"&gt;si&lt;/span&gt;&lt;span style="color: magenta;"&gt;"&lt;/span&gt; : &lt;span style="color: magenta;"&gt;"&lt;/span&gt;&lt;span style="color: magenta;"&gt;no&lt;/span&gt;&lt;span style="color: magenta;"&gt;"&lt;/span&gt;;&lt;br /&gt;&lt;span style="color: brown;"&gt;32 &lt;/span&gt;        &lt;span style="color: darkcyan;"&gt;$guess&lt;/span&gt;  = &lt;span style="color: darkcyan;"&gt;$node&lt;/span&gt;-&amp;gt;&lt;span style="color: darkcyan;"&gt;$branch&lt;/span&gt;;&lt;br /&gt;&lt;span style="color: brown;"&gt;33 &lt;/span&gt;    }&lt;br /&gt;&lt;span style="color: brown;"&gt;34 &lt;/span&gt;    &lt;span style="color: brown;"&gt;&lt;b&gt;return&lt;/b&gt;&lt;/span&gt; &lt;span style="color: brown;"&gt;&lt;b&gt;if&lt;/b&gt;&lt;/span&gt; &lt;span style="color: darkcyan;"&gt;$self&lt;/span&gt;&lt;span style="color: darkcyan;"&gt;-&amp;gt;si&lt;/span&gt;(&lt;span style="color: magenta;"&gt;"&lt;/span&gt;&lt;span style="color: magenta;"&gt;Es un(a) &lt;/span&gt;&lt;span style="color: darkcyan;"&gt;$guess&lt;/span&gt;&lt;span style="color: magenta;"&gt;"&lt;/span&gt;);&lt;br /&gt;&lt;span style="color: brown;"&gt;35 &lt;/span&gt;    &lt;span style="color: brown;"&gt;&lt;b&gt;my&lt;/b&gt;&lt;/span&gt; &lt;span style="color: darkcyan;"&gt;$animal&lt;/span&gt; = &lt;span style="color: darkcyan;"&gt;$self&lt;/span&gt;&lt;span style="color: darkcyan;"&gt;-&amp;gt;prompt&lt;/span&gt;(&lt;span style="color: magenta;"&gt;"&lt;/span&gt;&lt;span style="color: magenta;"&gt;Nombre del animal: &lt;/span&gt;&lt;span style="color: magenta;"&gt;"&lt;/span&gt;);&lt;br /&gt;&lt;span style="color: brown;"&gt;36 &lt;/span&gt;    &lt;span style="color: brown;"&gt;&lt;b&gt;my&lt;/b&gt;&lt;/span&gt; &lt;span style="color: darkcyan;"&gt;$diff&lt;/span&gt;   = &lt;span style="color: darkcyan;"&gt;$self&lt;/span&gt;&lt;span style="color: darkcyan;"&gt;-&amp;gt;prompt&lt;/span&gt;(&lt;br /&gt;&lt;span style="color: brown;"&gt;37 &lt;/span&gt;        &lt;span style="color: magenta;"&gt;"&lt;/span&gt;&lt;span style="color: magenta;"&gt;Una pregunta cierta para &lt;/span&gt;&lt;span style="color: darkcyan;"&gt;$animal&lt;/span&gt;&lt;span style="color: magenta;"&gt; pero falsa para &lt;/span&gt;&lt;span style="color: darkcyan;"&gt;$guess&lt;/span&gt;&lt;span style="color: magenta;"&gt;: &lt;/span&gt;&lt;span style="color: magenta;"&gt;"&lt;/span&gt;);&lt;br /&gt;&lt;span style="color: brown;"&gt;38 &lt;/span&gt;    &lt;span style="color: darkcyan;"&gt;$node&lt;/span&gt;-&amp;gt;&lt;span style="color: darkcyan;"&gt;$branch&lt;/span&gt;( QuestionNode-&amp;gt;&lt;span style="color: brown;"&gt;&lt;b&gt;new&lt;/b&gt;&lt;/span&gt;(&lt;br /&gt;&lt;span style="color: brown;"&gt;39 &lt;/span&gt;        { &lt;span style="color: magenta;"&gt;pregunta &lt;/span&gt;=&amp;gt; &lt;span style="color: darkcyan;"&gt;$diff&lt;/span&gt;, &lt;span style="color: magenta;"&gt;no &lt;/span&gt;=&amp;gt; &lt;span style="color: darkcyan;"&gt;$guess&lt;/span&gt;, &lt;span style="color: magenta;"&gt;si &lt;/span&gt;=&amp;gt; &lt;span style="color: darkcyan;"&gt;$animal&lt;/span&gt; } ) );&lt;br /&gt;&lt;span style="color: brown;"&gt;40 &lt;/span&gt;}&lt;br /&gt;&lt;span style="color: brown;"&gt;41 &lt;/span&gt;&lt;br /&gt;&lt;span style="color: brown;"&gt;42 &lt;/span&gt;&lt;span style="color: brown;"&gt;&lt;b&gt;sub&lt;/b&gt;&lt;/span&gt;&lt;span style="color: darkcyan;"&gt; &lt;/span&gt;&lt;span style="color: darkcyan;"&gt;new &lt;/span&gt;{&lt;br /&gt;&lt;span style="color: brown;"&gt;43 &lt;/span&gt;    &lt;span style="color: brown;"&gt;&lt;b&gt;my&lt;/b&gt;&lt;/span&gt; &lt;span style="color: darkcyan;"&gt;$class&lt;/span&gt; = &lt;span style="color: brown;"&gt;&lt;b&gt;shift&lt;/b&gt;&lt;/span&gt;;&lt;br /&gt;&lt;span style="color: brown;"&gt;44 &lt;/span&gt;    &lt;span style="color: brown;"&gt;&lt;b&gt;my&lt;/b&gt;&lt;/span&gt; &lt;span style="color: darkcyan;"&gt;$opt&lt;/span&gt;   = &lt;span style="color: brown;"&gt;&lt;b&gt;shift&lt;/b&gt;&lt;/span&gt; || {};&lt;br /&gt;&lt;span style="color: brown;"&gt;45 &lt;/span&gt;    &lt;span style="color: brown;"&gt;&lt;b&gt;my&lt;/b&gt;&lt;/span&gt; &lt;span style="color: darkcyan;"&gt;$title&lt;/span&gt; = &lt;span style="color: darkcyan;"&gt;$opt&lt;/span&gt;&lt;span style="color: darkcyan;"&gt;-&amp;gt;{&lt;/span&gt;&lt;span style="color: magenta;"&gt;title&lt;/span&gt;&lt;span style="color: darkcyan;"&gt;}&lt;/span&gt; || &lt;span style="color: magenta;"&gt;"&lt;/span&gt;&lt;span style="color: magenta;"&gt;El juego de los animales&lt;/span&gt;&lt;span style="color: magenta;"&gt;"&lt;/span&gt;;&lt;br /&gt;&lt;span style="color: brown;"&gt;46 &lt;/span&gt;    &lt;span style="color: brown;"&gt;&lt;b&gt;my&lt;/b&gt;&lt;/span&gt; &lt;span style="color: darkcyan;"&gt;$term&lt;/span&gt;  = &lt;span style="color: darkcyan;"&gt;$opt&lt;/span&gt;&lt;span style="color: darkcyan;"&gt;-&amp;gt;{&lt;/span&gt;&lt;span style="color: magenta;"&gt;term&lt;/span&gt;&lt;span style="color: darkcyan;"&gt;}&lt;/span&gt;  || Term::ReadLine-&amp;gt;&lt;span style="color: brown;"&gt;&lt;b&gt;new&lt;/b&gt;&lt;/span&gt;(&lt;span style="color: darkcyan;"&gt;$title&lt;/span&gt;);&lt;br /&gt;&lt;span style="color: brown;"&gt;47 &lt;/span&gt;    &lt;span style="color: brown;"&gt;&lt;b&gt;my&lt;/b&gt;&lt;/span&gt; &lt;span style="color: darkcyan;"&gt;$tree&lt;/span&gt;  = &lt;span style="color: darkcyan;"&gt;$opt&lt;/span&gt;&lt;span style="color: darkcyan;"&gt;-&amp;gt;{&lt;/span&gt;&lt;span style="color: magenta;"&gt;tree&lt;/span&gt;&lt;span style="color: darkcyan;"&gt;}&lt;/span&gt;  || QuestionNode-&amp;gt;&lt;span style="color: brown;"&gt;&lt;b&gt;new&lt;/b&gt;&lt;/span&gt;(&lt;br /&gt;&lt;span style="color: brown;"&gt;48 &lt;/span&gt;        { &lt;span style="color: magenta;"&gt;pregunta &lt;/span&gt;=&amp;gt; &lt;span style="color: magenta;"&gt;'&lt;/span&gt;&lt;span style="color: magenta;"&gt;vive en el agua&lt;/span&gt;&lt;span style="color: magenta;"&gt;'&lt;/span&gt;, &lt;span style="color: magenta;"&gt;no &lt;/span&gt;=&amp;gt; &lt;span style="color: magenta;"&gt;'&lt;/span&gt;&lt;span style="color: magenta;"&gt;tigre&lt;/span&gt;&lt;span style="color: magenta;"&gt;'&lt;/span&gt;, &lt;span style="color: magenta;"&gt;si &lt;/span&gt;=&amp;gt; &lt;span style="color: magenta;"&gt;'&lt;/span&gt;&lt;span style="color: magenta;"&gt;tiburón&lt;/span&gt;&lt;span style="color: magenta;"&gt;'&lt;/span&gt; } );&lt;br /&gt;&lt;span style="color: brown;"&gt;49 &lt;/span&gt;    &lt;span style="color: brown;"&gt;&lt;b&gt;return&lt;/b&gt;&lt;/span&gt; &lt;span style="color: darkcyan;"&gt;$class&lt;/span&gt;&lt;span style="color: darkcyan;"&gt;-&amp;gt;SUPER&lt;/span&gt;::&lt;span style="color: brown;"&gt;&lt;b&gt;new&lt;/b&gt;&lt;/span&gt;( { &lt;span style="color: magenta;"&gt;tree &lt;/span&gt;=&amp;gt; &lt;span style="color: darkcyan;"&gt;$tree&lt;/span&gt;, &lt;span style="color: magenta;"&gt;term &lt;/span&gt;=&amp;gt; &lt;span style="color: darkcyan;"&gt;$term&lt;/span&gt; } );&lt;br /&gt;&lt;span style="color: brown;"&gt;50 &lt;/span&gt;}&lt;br /&gt;&lt;span style="color: brown;"&gt;51 &lt;/span&gt;&lt;br /&gt;&lt;span style="color: brown;"&gt;52 &lt;/span&gt;&lt;span style="color: brown;"&gt;&lt;b&gt;sub&lt;/b&gt;&lt;/span&gt;&lt;span style="color: darkcyan;"&gt; &lt;/span&gt;&lt;span style="color: darkcyan;"&gt;run &lt;/span&gt;{&lt;br /&gt;&lt;span style="color: brown;"&gt;53 &lt;/span&gt;    &lt;span style="color: brown;"&gt;&lt;b&gt;my&lt;/b&gt;&lt;/span&gt; &lt;span style="color: darkcyan;"&gt;$self&lt;/span&gt; = &lt;span style="color: brown;"&gt;&lt;b&gt;shift&lt;/b&gt;&lt;/span&gt;;&lt;br /&gt;&lt;span style="color: brown;"&gt;54 &lt;/span&gt;    &lt;span style="color: darkcyan;"&gt;$self&lt;/span&gt;&lt;span style="color: darkcyan;"&gt;-&amp;gt;play&lt;/span&gt;;&lt;br /&gt;&lt;span style="color: brown;"&gt;55 &lt;/span&gt;    &lt;span style="color: darkcyan;"&gt;$self&lt;/span&gt;&lt;span style="color: darkcyan;"&gt;-&amp;gt;play&lt;/span&gt; &lt;span style="color: brown;"&gt;&lt;b&gt;while&lt;/b&gt;&lt;/span&gt; &lt;span style="color: darkcyan;"&gt;$self&lt;/span&gt;&lt;span style="color: darkcyan;"&gt;-&amp;gt;si&lt;/span&gt;(&lt;span style="color: magenta;"&gt;"&lt;/span&gt;&lt;span style="color: magenta;"&gt;Quieres jugar de nuevo&lt;/span&gt;&lt;span style="color: magenta;"&gt;"&lt;/span&gt;);&lt;br /&gt;&lt;span style="color: brown;"&gt;56 &lt;/span&gt;}&lt;br /&gt;&lt;span style="color: brown;"&gt;57 &lt;/span&gt;&lt;br /&gt;&lt;span style="color: brown;"&gt;58 &lt;/span&gt;&lt;span style="color: magenta;"&gt;1&lt;/span&gt;;&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;Las herramientas de asistencia de OOP captaron la atención del programador y los programas en Perl, se hicieron más fáciles de entender y programar de manera robusta.&lt;br /&gt;&lt;br /&gt;&lt;h2&gt;Moose&lt;/h2&gt;&lt;br /&gt;Este sistema es la última palabra en OOP para Perl.&lt;br /&gt;&lt;br /&gt;En particular voy a mostrar como sería el programa utilizando herencia múltiple y composición (roles, rasgos, mixins, ...), yo me estoy volviendo un fanático de la última, pues permite implementar objetos como jugar con LEGO evitando algunos problemas comunes de la herencia múltiple. Sin embargo, primero el ejemplo con herencia múltiple.&lt;br /&gt;&lt;br /&gt;Estilo 7: Moose con herencia múltiple&lt;br /&gt;&lt;br /&gt;game.pl:&lt;br /&gt;&lt;pre&gt;&lt;span style="color: brown;"&gt; 1 &lt;/span&gt;&lt;span style="color: #a020f0;"&gt;#!/usr/bin/env perl&lt;/span&gt;&lt;br /&gt;&lt;span style="color: brown;"&gt; 2 &lt;/span&gt;&lt;span style="color: brown;"&gt;&lt;b&gt;package&lt;/b&gt;&lt;/span&gt;&lt;span style="color: seagreen;"&gt;&lt;b&gt; Game;&lt;/b&gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="color: brown;"&gt; 3 &lt;/span&gt;&lt;span style="color: #a020f0;"&gt;use &lt;/span&gt;Moose;&lt;br /&gt;&lt;span style="color: brown;"&gt; 4 &lt;/span&gt;&lt;br /&gt;&lt;span style="color: brown;"&gt; 5 &lt;/span&gt;extends &lt;span style="color: magenta;"&gt;qw(&lt;/span&gt;&lt;span style="color: magenta;"&gt;AnimalsGame ConsoleGame&lt;/span&gt;&lt;span style="color: magenta;"&gt;)&lt;/span&gt;;&lt;br /&gt;&lt;span style="color: brown;"&gt; 6 &lt;/span&gt;&lt;br /&gt;&lt;span style="color: brown;"&gt; 7 &lt;/span&gt;__PACKAGE__-&amp;gt;meta-&amp;gt;make_immutable;&lt;br /&gt;&lt;span style="color: brown;"&gt; 8 &lt;/span&gt;&lt;span style="color: #a020f0;"&gt;no &lt;/span&gt;Moose;&lt;br /&gt;&lt;span style="color: brown;"&gt; 9 &lt;/span&gt;&lt;br /&gt;&lt;span style="color: brown;"&gt;10 &lt;/span&gt;Game-&amp;gt;&lt;span style="color: brown;"&gt;&lt;b&gt;new&lt;/b&gt;&lt;/span&gt;-&amp;gt;run;&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;AnimalsGame.pm:&lt;br /&gt;&lt;pre&gt;&lt;span style="color: brown;"&gt; 1 &lt;/span&gt;&lt;span style="color: brown;"&gt;&lt;b&gt;package&lt;/b&gt;&lt;/span&gt;&lt;span style="color: seagreen;"&gt;&lt;b&gt; AnimalsGame;&lt;/b&gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="color: brown;"&gt; 2 &lt;/span&gt;&lt;span style="color: #a020f0;"&gt;use &lt;/span&gt;Moose;&lt;br /&gt;&lt;span style="color: brown;"&gt; 3 &lt;/span&gt;&lt;span style="color: #a020f0;"&gt;use &lt;/span&gt;QuestionNode;&lt;br /&gt;&lt;span style="color: brown;"&gt; 4 &lt;/span&gt;&lt;br /&gt;&lt;span style="color: brown;"&gt; 5 &lt;/span&gt;has &lt;span style="color: magenta;"&gt;tree &lt;/span&gt;=&amp;gt; (&lt;br /&gt;&lt;span style="color: brown;"&gt; 6 &lt;/span&gt;    &lt;span style="color: magenta;"&gt;is      &lt;/span&gt;=&amp;gt; &lt;span style="color: magenta;"&gt;"&lt;/span&gt;&lt;span style="color: magenta;"&gt;ro&lt;/span&gt;&lt;span style="color: magenta;"&gt;"&lt;/span&gt;,&lt;br /&gt;&lt;span style="color: brown;"&gt; 7 &lt;/span&gt;    &lt;span style="color: magenta;"&gt;isa     &lt;/span&gt;=&amp;gt; &lt;span style="color: magenta;"&gt;"&lt;/span&gt;&lt;span style="color: magenta;"&gt;QuestionNode&lt;/span&gt;&lt;span style="color: magenta;"&gt;"&lt;/span&gt;,&lt;br /&gt;&lt;span style="color: brown;"&gt; 8 &lt;/span&gt;    &lt;span style="color: magenta;"&gt;default &lt;/span&gt;=&amp;gt;&lt;span style="color: darkcyan;"&gt; &lt;/span&gt;&lt;span style="color: brown;"&gt;&lt;b&gt;sub&lt;/b&gt;&lt;/span&gt;&lt;span style="color: darkcyan;"&gt; &lt;/span&gt;{&lt;br /&gt;&lt;span style="color: brown;"&gt; 9 &lt;/span&gt;        QuestionNode-&amp;gt;&lt;span style="color: brown;"&gt;&lt;b&gt;new&lt;/b&gt;&lt;/span&gt;(&lt;br /&gt;&lt;span style="color: brown;"&gt;10 &lt;/span&gt;            { &lt;span style="color: magenta;"&gt;pregunta &lt;/span&gt;=&amp;gt; &lt;span style="color: magenta;"&gt;'&lt;/span&gt;&lt;span style="color: magenta;"&gt;vive en el agua&lt;/span&gt;&lt;span style="color: magenta;"&gt;'&lt;/span&gt;, &lt;span style="color: magenta;"&gt;no &lt;/span&gt;=&amp;gt; &lt;span style="color: magenta;"&gt;'&lt;/span&gt;&lt;span style="color: magenta;"&gt;tigre&lt;/span&gt;&lt;span style="color: magenta;"&gt;'&lt;/span&gt;, &lt;span style="color: magenta;"&gt;si &lt;/span&gt;=&amp;gt; &lt;span style="color: magenta;"&gt;'&lt;/span&gt;&lt;span style="color: magenta;"&gt;tiburón&lt;/span&gt;&lt;span style="color: magenta;"&gt;'&lt;/span&gt; } );&lt;br /&gt;&lt;span style="color: brown;"&gt;11 &lt;/span&gt;    }&lt;br /&gt;&lt;span style="color: brown;"&gt;12 &lt;/span&gt;);&lt;br /&gt;&lt;span style="color: brown;"&gt;13 &lt;/span&gt;&lt;br /&gt;&lt;span style="color: brown;"&gt;14 &lt;/span&gt;&lt;span style="color: brown;"&gt;&lt;b&gt;sub&lt;/b&gt;&lt;/span&gt;&lt;span style="color: darkcyan;"&gt; &lt;/span&gt;&lt;span style="color: darkcyan;"&gt;play &lt;/span&gt;{&lt;br /&gt;&lt;span style="color: brown;"&gt;15 &lt;/span&gt;    &lt;span style="color: brown;"&gt;&lt;b&gt;my&lt;/b&gt;&lt;/span&gt; &lt;span style="color: darkcyan;"&gt;$self&lt;/span&gt;  = &lt;span style="color: brown;"&gt;&lt;b&gt;shift&lt;/b&gt;&lt;/span&gt;;&lt;br /&gt;&lt;span style="color: brown;"&gt;16 &lt;/span&gt;    &lt;span style="color: brown;"&gt;&lt;b&gt;my&lt;/b&gt;&lt;/span&gt; &lt;span style="color: darkcyan;"&gt;$guess&lt;/span&gt; = &lt;span style="color: darkcyan;"&gt;$self&lt;/span&gt;&lt;span style="color: darkcyan;"&gt;-&amp;gt;tree&lt;/span&gt;;&lt;br /&gt;&lt;span style="color: brown;"&gt;17 &lt;/span&gt;    &lt;span style="color: brown;"&gt;&lt;b&gt;my&lt;/b&gt;&lt;/span&gt; ( &lt;span style="color: darkcyan;"&gt;$node&lt;/span&gt;, &lt;span style="color: darkcyan;"&gt;$branch&lt;/span&gt; );&lt;br /&gt;&lt;span style="color: brown;"&gt;18 &lt;/span&gt;    &lt;span style="color: brown;"&gt;&lt;b&gt;while&lt;/b&gt;&lt;/span&gt; ( &lt;span style="color: brown;"&gt;&lt;b&gt;ref&lt;/b&gt;&lt;/span&gt;(&lt;span style="color: darkcyan;"&gt;$guess&lt;/span&gt;) ) {&lt;br /&gt;&lt;span style="color: brown;"&gt;19 &lt;/span&gt;        &lt;span style="color: darkcyan;"&gt;$node&lt;/span&gt;   = &lt;span style="color: darkcyan;"&gt;$guess&lt;/span&gt;;&lt;br /&gt;&lt;span style="color: brown;"&gt;20 &lt;/span&gt;        &lt;span style="color: darkcyan;"&gt;$branch&lt;/span&gt; = &lt;span style="color: darkcyan;"&gt;$self&lt;/span&gt;&lt;span style="color: darkcyan;"&gt;-&amp;gt;si&lt;/span&gt;( &lt;span style="color: darkcyan;"&gt;$node&lt;/span&gt;&lt;span style="color: darkcyan;"&gt;-&amp;gt;pregunta&lt;/span&gt; ) ? &lt;span style="color: magenta;"&gt;"&lt;/span&gt;&lt;span style="color: magenta;"&gt;si&lt;/span&gt;&lt;span style="color: magenta;"&gt;"&lt;/span&gt; : &lt;span style="color: magenta;"&gt;"&lt;/span&gt;&lt;span style="color: magenta;"&gt;no&lt;/span&gt;&lt;span style="color: magenta;"&gt;"&lt;/span&gt;;&lt;br /&gt;&lt;span style="color: brown;"&gt;21 &lt;/span&gt;        &lt;span style="color: darkcyan;"&gt;$guess&lt;/span&gt;  = &lt;span style="color: darkcyan;"&gt;$node&lt;/span&gt;-&amp;gt;&lt;span style="color: darkcyan;"&gt;$branch&lt;/span&gt;;&lt;br /&gt;&lt;span style="color: brown;"&gt;22 &lt;/span&gt;    }&lt;br /&gt;&lt;span style="color: brown;"&gt;23 &lt;/span&gt;    &lt;span style="color: brown;"&gt;&lt;b&gt;return&lt;/b&gt;&lt;/span&gt; &lt;span style="color: brown;"&gt;&lt;b&gt;if&lt;/b&gt;&lt;/span&gt; &lt;span style="color: darkcyan;"&gt;$self&lt;/span&gt;&lt;span style="color: darkcyan;"&gt;-&amp;gt;si&lt;/span&gt;(&lt;span style="color: magenta;"&gt;"&lt;/span&gt;&lt;span style="color: magenta;"&gt;Es un(a) &lt;/span&gt;&lt;span style="color: darkcyan;"&gt;$guess&lt;/span&gt;&lt;span style="color: magenta;"&gt;"&lt;/span&gt;);&lt;br /&gt;&lt;span style="color: brown;"&gt;24 &lt;/span&gt;    &lt;span style="color: brown;"&gt;&lt;b&gt;my&lt;/b&gt;&lt;/span&gt; &lt;span style="color: darkcyan;"&gt;$animal&lt;/span&gt; = &lt;span style="color: darkcyan;"&gt;$self&lt;/span&gt;&lt;span style="color: darkcyan;"&gt;-&amp;gt;prompt&lt;/span&gt;(&lt;span style="color: magenta;"&gt;"&lt;/span&gt;&lt;span style="color: magenta;"&gt;Nombre del animal: &lt;/span&gt;&lt;span style="color: magenta;"&gt;"&lt;/span&gt;);&lt;br /&gt;&lt;span style="color: brown;"&gt;25 &lt;/span&gt;    &lt;span style="color: brown;"&gt;&lt;b&gt;my&lt;/b&gt;&lt;/span&gt; &lt;span style="color: darkcyan;"&gt;$diff&lt;/span&gt;   = &lt;span style="color: darkcyan;"&gt;$self&lt;/span&gt;&lt;span style="color: darkcyan;"&gt;-&amp;gt;prompt&lt;/span&gt;(&lt;br /&gt;&lt;span style="color: brown;"&gt;26 &lt;/span&gt;        &lt;span style="color: magenta;"&gt;"&lt;/span&gt;&lt;span style="color: magenta;"&gt;Una pregunta cierta para &lt;/span&gt;&lt;span style="color: darkcyan;"&gt;$animal&lt;/span&gt;&lt;span style="color: magenta;"&gt; pero falsa para &lt;/span&gt;&lt;span style="color: darkcyan;"&gt;$guess&lt;/span&gt;&lt;span style="color: magenta;"&gt;: &lt;/span&gt;&lt;span style="color: magenta;"&gt;"&lt;/span&gt;);&lt;br /&gt;&lt;span style="color: brown;"&gt;27 &lt;/span&gt;    &lt;span style="color: darkcyan;"&gt;$node&lt;/span&gt;-&amp;gt;&lt;span style="color: darkcyan;"&gt;$branch&lt;/span&gt;(&lt;br /&gt;&lt;span style="color: brown;"&gt;28 &lt;/span&gt;        QuestionNode-&amp;gt;&lt;span style="color: brown;"&gt;&lt;b&gt;new&lt;/b&gt;&lt;/span&gt;( { &lt;span style="color: magenta;"&gt;pregunta &lt;/span&gt;=&amp;gt; &lt;span style="color: darkcyan;"&gt;$diff&lt;/span&gt;, &lt;span style="color: magenta;"&gt;no &lt;/span&gt;=&amp;gt; &lt;span style="color: darkcyan;"&gt;$guess&lt;/span&gt;, &lt;span style="color: magenta;"&gt;si &lt;/span&gt;=&amp;gt; &lt;span style="color: darkcyan;"&gt;$animal&lt;/span&gt; } ) );&lt;br /&gt;&lt;span style="color: brown;"&gt;29 &lt;/span&gt;}&lt;br /&gt;&lt;span style="color: brown;"&gt;30 &lt;/span&gt;&lt;br /&gt;&lt;span style="color: brown;"&gt;31 &lt;/span&gt;__PACKAGE__-&amp;gt;meta-&amp;gt;make_immutable;&lt;br /&gt;&lt;span style="color: brown;"&gt;32 &lt;/span&gt;&lt;span style="color: magenta;"&gt;1&lt;/span&gt;;&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;ConsoleGame.pm:&lt;br /&gt;&lt;pre&gt;&lt;span style="color: brown;"&gt; 1 &lt;/span&gt;&lt;span style="color: brown;"&gt;&lt;b&gt;package&lt;/b&gt;&lt;/span&gt;&lt;span style="color: seagreen;"&gt;&lt;b&gt; ConsoleGame;&lt;/b&gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="color: brown;"&gt; 2 &lt;/span&gt;&lt;span style="color: #a020f0;"&gt;use &lt;/span&gt;Moose;&lt;br /&gt;&lt;span style="color: brown;"&gt; 3 &lt;/span&gt;&lt;span style="color: #a020f0;"&gt;use &lt;/span&gt;Term::ReadLine;&lt;br /&gt;&lt;span style="color: brown;"&gt; 4 &lt;/span&gt;&lt;span style="color: #a020f0;"&gt;use &lt;/span&gt;IO::Handle;&lt;br /&gt;&lt;span style="color: brown;"&gt; 5 &lt;/span&gt;&lt;br /&gt;&lt;span style="color: brown;"&gt; 6 &lt;/span&gt;has &lt;span style="color: magenta;"&gt;title &lt;/span&gt;=&amp;gt; ( &lt;span style="color: magenta;"&gt;is &lt;/span&gt;=&amp;gt; &lt;span style="color: magenta;"&gt;"&lt;/span&gt;&lt;span style="color: magenta;"&gt;ro&lt;/span&gt;&lt;span style="color: magenta;"&gt;"&lt;/span&gt;, &lt;span style="color: magenta;"&gt;isa &lt;/span&gt;=&amp;gt; &lt;span style="color: magenta;"&gt;"&lt;/span&gt;&lt;span style="color: magenta;"&gt;Str&lt;/span&gt;&lt;span style="color: magenta;"&gt;"&lt;/span&gt;, &lt;span style="color: magenta;"&gt;default &lt;/span&gt;=&amp;gt; &lt;span style="color: magenta;"&gt;"&lt;/span&gt;&lt;span style="color: magenta;"&gt;El juego de los animales&lt;/span&gt;&lt;span style="color: magenta;"&gt;"&lt;/span&gt; );&lt;br /&gt;&lt;span style="color: brown;"&gt; 7 &lt;/span&gt;has &lt;span style="color: magenta;"&gt;term  &lt;/span&gt;=&amp;gt; ( &lt;span style="color: magenta;"&gt;is &lt;/span&gt;=&amp;gt; &lt;span style="color: magenta;"&gt;"&lt;/span&gt;&lt;span style="color: magenta;"&gt;ro&lt;/span&gt;&lt;span style="color: magenta;"&gt;"&lt;/span&gt;, &lt;span style="color: magenta;"&gt;isa &lt;/span&gt;=&amp;gt; &lt;span style="color: magenta;"&gt;"&lt;/span&gt;&lt;span style="color: magenta;"&gt;Object&lt;/span&gt;&lt;span style="color: magenta;"&gt;"&lt;/span&gt;, &lt;span style="color: magenta;"&gt;lazy_build &lt;/span&gt;=&amp;gt; &lt;span style="color: magenta;"&gt;1&lt;/span&gt;,&lt;br /&gt;&lt;span style="color: brown;"&gt; 8 &lt;/span&gt;               &lt;span style="color: magenta;"&gt;handles &lt;/span&gt;=&amp;gt; { &lt;span style="color: magenta;"&gt;prompt &lt;/span&gt;=&amp;gt; &lt;span style="color: magenta;"&gt;"&lt;/span&gt;&lt;span style="color: magenta;"&gt;readline&lt;/span&gt;&lt;span style="color: magenta;"&gt;"&lt;/span&gt; } );&lt;br /&gt;&lt;span style="color: brown;"&gt; 9 &lt;/span&gt;&lt;br /&gt;&lt;span style="color: brown;"&gt;10 &lt;/span&gt;&lt;span style="color: brown;"&gt;&lt;b&gt;sub&lt;/b&gt;&lt;/span&gt;&lt;span style="color: darkcyan;"&gt; &lt;/span&gt;&lt;span style="color: darkcyan;"&gt;_build_term &lt;/span&gt;{&lt;br /&gt;&lt;span style="color: brown;"&gt;11 &lt;/span&gt;    &lt;span style="color: brown;"&gt;&lt;b&gt;my&lt;/b&gt;&lt;/span&gt; &lt;span style="color: darkcyan;"&gt;$self&lt;/span&gt; = &lt;span style="color: brown;"&gt;&lt;b&gt;shift&lt;/b&gt;&lt;/span&gt;;&lt;br /&gt;&lt;span style="color: brown;"&gt;12 &lt;/span&gt;    Term::ReadLine-&amp;gt;&lt;span style="color: brown;"&gt;&lt;b&gt;new&lt;/b&gt;&lt;/span&gt;( &lt;span style="color: darkcyan;"&gt;$self&lt;/span&gt;&lt;span style="color: darkcyan;"&gt;-&amp;gt;title&lt;/span&gt; );&lt;br /&gt;&lt;span style="color: brown;"&gt;13 &lt;/span&gt;}&lt;br /&gt;&lt;span style="color: brown;"&gt;14 &lt;/span&gt;&lt;br /&gt;&lt;span style="color: brown;"&gt;15 &lt;/span&gt;&lt;span style="color: brown;"&gt;&lt;b&gt;sub&lt;/b&gt;&lt;/span&gt;&lt;span style="color: darkcyan;"&gt; &lt;/span&gt;&lt;span style="color: darkcyan;"&gt;si &lt;/span&gt;{&lt;br /&gt;&lt;span style="color: brown;"&gt;16 &lt;/span&gt;    &lt;span style="color: brown;"&gt;&lt;b&gt;my&lt;/b&gt;&lt;/span&gt; &lt;span style="color: darkcyan;"&gt;$self&lt;/span&gt;   = &lt;span style="color: brown;"&gt;&lt;b&gt;shift&lt;/b&gt;&lt;/span&gt;;&lt;br /&gt;&lt;span style="color: brown;"&gt;17 &lt;/span&gt;    &lt;span style="color: brown;"&gt;&lt;b&gt;my&lt;/b&gt;&lt;/span&gt; &lt;span style="color: darkcyan;"&gt;$prompt&lt;/span&gt; = &lt;span style="color: brown;"&gt;&lt;b&gt;shift&lt;/b&gt;&lt;/span&gt;;&lt;br /&gt;&lt;span style="color: brown;"&gt;18 &lt;/span&gt;    &lt;span style="color: brown;"&gt;&lt;b&gt;while&lt;/b&gt;&lt;/span&gt; (&lt;span style="color: magenta;"&gt;1&lt;/span&gt;) {&lt;br /&gt;&lt;span style="color: brown;"&gt;19 &lt;/span&gt;        &lt;span style="color: brown;"&gt;&lt;b&gt;my&lt;/b&gt;&lt;/span&gt; &lt;span style="color: darkcyan;"&gt;$answer&lt;/span&gt; = &lt;span style="color: darkcyan;"&gt;$self&lt;/span&gt;&lt;span style="color: darkcyan;"&gt;-&amp;gt;prompt&lt;/span&gt;(&lt;span style="color: magenta;"&gt;"&lt;/span&gt;&lt;span style="color: darkcyan;"&gt;$prompt&lt;/span&gt;&lt;span style="color: magenta;"&gt;? (y/n): &lt;/span&gt;&lt;span style="color: magenta;"&gt;"&lt;/span&gt;);&lt;br /&gt;&lt;span style="color: brown;"&gt;20 &lt;/span&gt;        &lt;span style="color: brown;"&gt;&lt;b&gt;return&lt;/b&gt;&lt;/span&gt; ( &lt;span style="color: darkcyan;"&gt;$2&lt;/span&gt; ? &lt;span style="color: magenta;"&gt;1&lt;/span&gt; : &lt;span style="color: magenta;"&gt;0&lt;/span&gt; ) &lt;span style="color: brown;"&gt;&lt;b&gt;if&lt;/b&gt;&lt;/span&gt; &lt;span style="color: darkcyan;"&gt;$answer&lt;/span&gt; =~&lt;span style="color: brown;"&gt;&lt;b&gt; /&lt;/b&gt;&lt;/span&gt;&lt;span style="color: magenta;"&gt;^&lt;/span&gt;&lt;span style="color: slateblue;"&gt;\s&lt;/span&gt;&lt;span style="color: slateblue;"&gt;*((&lt;/span&gt;&lt;span style="color: magenta;"&gt;si|s&lt;/span&gt;&lt;span style="color: slateblue;"&gt;)&lt;/span&gt;&lt;span style="color: magenta;"&gt;|&lt;/span&gt;&lt;span style="color: slateblue;"&gt;(&lt;/span&gt;&lt;span style="color: magenta;"&gt;no|n&lt;/span&gt;&lt;span style="color: slateblue;"&gt;))&lt;/span&gt;&lt;span style="color: slateblue;"&gt;\s&lt;/span&gt;&lt;span style="color: slateblue;"&gt;*&lt;/span&gt;&lt;span style="color: brown;"&gt;&lt;b&gt;/i&lt;/b&gt;&lt;/span&gt;;&lt;br /&gt;&lt;span style="color: brown;"&gt;21 &lt;/span&gt;        &lt;span style="color: darkcyan;"&gt;$self&lt;/span&gt;&lt;span style="color: darkcyan;"&gt;-&amp;gt;term&lt;/span&gt;-&amp;gt;OUT-&amp;gt;&lt;span style="color: brown;"&gt;&lt;b&gt;print&lt;/b&gt;&lt;/span&gt;(&lt;span style="color: magenta;"&gt;"&lt;/span&gt;&lt;span style="color: magenta;"&gt;Responde 's' o 'n'&lt;/span&gt;&lt;span style="color: slateblue;"&gt;\n&lt;/span&gt;&lt;span style="color: magenta;"&gt;"&lt;/span&gt;);&lt;br /&gt;&lt;span style="color: brown;"&gt;22 &lt;/span&gt;    }&lt;br /&gt;&lt;span style="color: brown;"&gt;23 &lt;/span&gt;}&lt;br /&gt;&lt;span style="color: brown;"&gt;24 &lt;/span&gt;&lt;br /&gt;&lt;span style="color: brown;"&gt;25 &lt;/span&gt;&lt;span style="color: brown;"&gt;&lt;b&gt;sub&lt;/b&gt;&lt;/span&gt;&lt;span style="color: darkcyan;"&gt; &lt;/span&gt;&lt;span style="color: darkcyan;"&gt;run &lt;/span&gt;{&lt;br /&gt;&lt;span style="color: brown;"&gt;26 &lt;/span&gt;    &lt;span style="color: brown;"&gt;&lt;b&gt;my&lt;/b&gt;&lt;/span&gt; &lt;span style="color: darkcyan;"&gt;$self&lt;/span&gt; = &lt;span style="color: brown;"&gt;&lt;b&gt;shift&lt;/b&gt;&lt;/span&gt;;&lt;br /&gt;&lt;span style="color: brown;"&gt;27 &lt;/span&gt;    &lt;span style="color: darkcyan;"&gt;$self&lt;/span&gt;&lt;span style="color: darkcyan;"&gt;-&amp;gt;play&lt;/span&gt;;&lt;br /&gt;&lt;span style="color: brown;"&gt;28 &lt;/span&gt;    &lt;span style="color: darkcyan;"&gt;$self&lt;/span&gt;&lt;span style="color: darkcyan;"&gt;-&amp;gt;play&lt;/span&gt; &lt;span style="color: brown;"&gt;&lt;b&gt;while&lt;/b&gt;&lt;/span&gt; &lt;span style="color: darkcyan;"&gt;$self&lt;/span&gt;&lt;span style="color: darkcyan;"&gt;-&amp;gt;si&lt;/span&gt;(&lt;span style="color: magenta;"&gt;"&lt;/span&gt;&lt;span style="color: magenta;"&gt;Quieres jugar de nuevo&lt;/span&gt;&lt;span style="color: magenta;"&gt;"&lt;/span&gt;);&lt;br /&gt;&lt;span style="color: brown;"&gt;29 &lt;/span&gt;}&lt;br /&gt;&lt;span style="color: brown;"&gt;30 &lt;/span&gt;&lt;br /&gt;&lt;span style="color: brown;"&gt;31 &lt;/span&gt;__PACKAGE__-&amp;gt;meta-&amp;gt;make_immutable;&lt;br /&gt;&lt;span style="color: brown;"&gt;32 &lt;/span&gt;&lt;span style="color: magenta;"&gt;1&lt;/span&gt;;&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;QuestionNode.pm&lt;br /&gt;&lt;pre&gt;&lt;span style="color: brown;"&gt;1 &lt;/span&gt;&lt;span style="color: brown;"&gt;&lt;b&gt;package&lt;/b&gt;&lt;/span&gt;&lt;span style="color: seagreen;"&gt;&lt;b&gt; QuestionNode;&lt;/b&gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="color: brown;"&gt;2 &lt;/span&gt;&lt;span style="color: #a020f0;"&gt;use &lt;/span&gt;Moose;&lt;br /&gt;&lt;span style="color: brown;"&gt;3 &lt;/span&gt;&lt;br /&gt;&lt;span style="color: brown;"&gt;4 &lt;/span&gt;has &lt;span style="color: magenta;"&gt;pregunta &lt;/span&gt;=&amp;gt; ( &lt;span style="color: magenta;"&gt;is &lt;/span&gt;=&amp;gt; &lt;span style="color: magenta;"&gt;"&lt;/span&gt;&lt;span style="color: magenta;"&gt;ro&lt;/span&gt;&lt;span style="color: magenta;"&gt;"&lt;/span&gt;, &lt;span style="color: magenta;"&gt;isa &lt;/span&gt;=&amp;gt; &lt;span style="color: magenta;"&gt;"&lt;/span&gt;&lt;span style="color: magenta;"&gt;Str&lt;/span&gt;&lt;span style="color: magenta;"&gt;"&lt;/span&gt;, &lt;span style="color: magenta;"&gt;required &lt;/span&gt;=&amp;gt; &lt;span style="color: magenta;"&gt;1&lt;/span&gt; );&lt;br /&gt;&lt;span style="color: brown;"&gt;5 &lt;/span&gt;has [ &lt;span style="color: magenta;"&gt;"&lt;/span&gt;&lt;span style="color: magenta;"&gt;si&lt;/span&gt;&lt;span style="color: magenta;"&gt;"&lt;/span&gt;, &lt;span style="color: magenta;"&gt;"&lt;/span&gt;&lt;span style="color: magenta;"&gt;no&lt;/span&gt;&lt;span style="color: magenta;"&gt;"&lt;/span&gt; ] =&amp;gt; ( &lt;span style="color: magenta;"&gt;is &lt;/span&gt;=&amp;gt; &lt;span style="color: magenta;"&gt;"&lt;/span&gt;&lt;span style="color: magenta;"&gt;rw&lt;/span&gt;&lt;span style="color: magenta;"&gt;"&lt;/span&gt;, &lt;span style="color: magenta;"&gt;isa &lt;/span&gt;=&amp;gt; &lt;span style="color: magenta;"&gt;"&lt;/span&gt;&lt;span style="color: magenta;"&gt;Str|QuestionNode&lt;/span&gt;&lt;span style="color: magenta;"&gt;"&lt;/span&gt;, &lt;span style="color: magenta;"&gt;required &lt;/span&gt;=&amp;gt; &lt;span style="color: magenta;"&gt;1&lt;/span&gt; );&lt;br /&gt;&lt;span style="color: brown;"&gt;6 &lt;/span&gt;&lt;br /&gt;&lt;span style="color: brown;"&gt;7 &lt;/span&gt;__PACKAGE__-&amp;gt;meta-&amp;gt;make_immutable;&lt;br /&gt;&lt;span style="color: brown;"&gt;8 &lt;/span&gt;&lt;span style="color: magenta;"&gt;1&lt;/span&gt;;&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;Moose es capaz de generar una cantidad de código muy superior a la de herramientas anteriores, que se limitaban a generar las clases y los accessors para los atributos, en Moose se pueden especificar restricciones de tipo, que pueden llegar a ser complejas. Así en QuestionNode "pregunta" es un "Str" (cadena de caracteres), mientras que "si" y "no" pueden ser "Str" o un objeto "QuestionNode", Moose se encarga de implementar todo el código para garantizar ese contrato.&lt;br /&gt;&lt;br /&gt;A continuación el ejemplo utilizando composición de objetos, una de las características más resaltantes de este ejemplo es que casi no hay que cambiar nada para utilizar la composición de objetos, lo que habla bastante bien de las capacidades de abstracción de Moose para la reutilización de código.&lt;br /&gt;&lt;br /&gt;En este caso la clase Game se arma agregando una clase ConsoleGame (con sus atributos) y una clase AnimalsGame que a su vez usa objetos del tipo QuestionNode.&lt;br /&gt;&lt;br /&gt;Estilo 8: Moose con Roles.&lt;br /&gt;&lt;br /&gt;en game.pl solo cambia en la línea 5, "extend" por "with":&lt;br /&gt;&lt;pre&gt;&lt;span style="color: brown;"&gt;&amp;nbsp;&lt;/span&gt;&lt;br /&gt;&lt;span style="color: brown;"&gt; 5 &lt;/span&gt;with &lt;span style="color: magenta;"&gt;qw(&lt;/span&gt;&lt;span style="color: magenta;"&gt;AnimalsGame ConsoleGame&lt;/span&gt;&lt;span style="color: magenta;"&gt;)&lt;/span&gt;;&lt;span style="color: brown;"&gt;&lt;/span&gt;&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;en AnimalsGame.pm y ConsoleGame.pm solo se cambia la línea 2 para convertir las clases en roles y se elimina la línea 31 que solo tiene sentido para las clases (solo las clases necesitan hacerse inmutables para tener un mejor rendimiento).&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;span style="color: brown;"&gt;&lt;/span&gt;&lt;span style="color: brown;"&gt; 2 &lt;/span&gt;&lt;span style="color: #a020f0;"&gt;use &lt;/span&gt;Moose::Role;&lt;br /&gt;&lt;span style="color: brown;"&gt;&lt;/span&gt;&lt;/pre&gt;Espero que este artículo te ayude a establecer similitudes y paralelos entre las técnicas que actualmente usas y Moose, que es básicamente el futuro de la programación orientada a objetos en Perl5, pero que además es la manera más fácil de aprender y afianzar conceptos que te serán útiles cuando quieras comenzar a utilizar Perl6.&lt;br /&gt;&lt;br /&gt;Otra ventaja (quizás más importante) de programar en Moose, es lograr un estándar de OOP que todos puedan aprender fácilmente, la diversidad de sistemas de OOP, no le hace del todo bien al lenguaje, ya que por alguna razón la gente quiere una sola interfaz, Moose hace esto posible ya que es lo suficiente flexible y potente para implementar cualquier cualquier cosa que se te ocurra.&lt;br /&gt;&lt;br /&gt;No esperes más. usa Moose. ¡YA!&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5238463735728501931-9058356365545384379?l=perliscopio.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://perliscopio.blogspot.com/feeds/9058356365545384379/comments/default' title='Enviar comentarios'/><link rel='replies' type='text/html' href='http://perliscopio.blogspot.com/2010/01/evolucion-del-estilo-en-perl.html#comment-form' title='3 comentarios'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5238463735728501931/posts/default/9058356365545384379'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5238463735728501931/posts/default/9058356365545384379'/><link rel='alternate' type='text/html' href='http://perliscopio.blogspot.com/2010/01/evolucion-del-estilo-en-perl.html' title='Evolución del estilo en Perl'/><author><name>Jose Rey</name><uri>http://www.blogger.com/profile/15071755167581242815</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>3</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5238463735728501931.post-5654221123234274523</id><published>2010-01-04T03:40:00.003-04:30</published><updated>2010-01-11T00:47:33.082-04:30</updated><category scheme='http://www.blogger.com/atom/ns#' term='Tutorial'/><category scheme='http://www.blogger.com/atom/ns#' term='Perl'/><category scheme='http://www.blogger.com/atom/ns#' term='CPAN'/><category scheme='http://www.blogger.com/atom/ns#' term='Moose'/><title type='text'>Atributos con rasgos en Moose.</title><content type='html'>[&lt;a href="http://translate.google.com/translate?js=y&amp;amp;prev=_t&amp;amp;hl=en&amp;amp;ie=UTF-8&amp;amp;layout=1&amp;amp;eotf=1&amp;amp;u=http%3A%2F%2Fperliscopio.blogspot.com%2F2010%2F01%2Fatributos-con-rasgos-en-moose.html&amp;amp;sl=es&amp;amp;tl=en"&gt;Google translation&lt;/a&gt;]&lt;br /&gt;En el &lt;a href="http://perliscopio.blogspot.com/2009/12/conociendo-moose.html"&gt;articulo anterior&lt;/a&gt; vimos lo más básico de Moose, sin embargo una vez que comiences a conocer este sistema de OOP verás que tiene un monton de mecanismos (y conceptos) que facilitan muchas cosas, uno de los más útiles son los rasgos (traits), que permiten aplicar comportamientos a una clase o atributo con mucha facilidad.&lt;br /&gt;&lt;br /&gt;Una característica de los rasgos en los atributos es que facilitan el uso de los mismos y permiten operaciones más eficientes.&lt;br /&gt;&lt;br /&gt;Veamos un ejemplo, tomando la clase Point del &lt;a href="http://perliscopio.blogspot.com/2009/12/conociendo-moose.html"&gt;artículo anterior&lt;/a&gt;, a la cual le agregaré el método translate, que traslada un punto:&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;span style="color: brown;"&gt;23 &lt;/span&gt;&lt;span style="color: brown;"&gt;&lt;b&gt;sub&lt;/b&gt;&lt;/span&gt;&lt;span style="color: darkcyan;"&gt; &lt;/span&gt;&lt;span style="color: darkcyan;"&gt;translate &lt;/span&gt;{&lt;br /&gt;&lt;span style="color: brown;"&gt;24 &lt;/span&gt;    &lt;span style="color: brown;"&gt;&lt;b&gt;my&lt;/b&gt;&lt;/span&gt; (&lt;span style="color: darkcyan;"&gt;$self&lt;/span&gt;, &lt;span style="color: darkcyan;"&gt;$x_delta&lt;/span&gt;, &lt;span style="color: darkcyan;"&gt;$y_delta&lt;/span&gt;) = &lt;span style="color: darkcyan;"&gt;@_&lt;/span&gt;;&lt;br /&gt;&lt;span style="color: brown;"&gt;25 &lt;/span&gt;    &lt;span style="color: darkcyan;"&gt;$self&lt;/span&gt;&lt;span style="color: darkcyan;"&gt;-&amp;gt;x&lt;/span&gt;( &lt;span style="color: darkcyan;"&gt;$self&lt;/span&gt;&lt;span style="color: darkcyan;"&gt;-&amp;gt;x&lt;/span&gt; + &lt;span style="color: darkcyan;"&gt;$x_delta&lt;/span&gt; );&lt;br /&gt;&lt;span style="color: brown;"&gt;26 &lt;/span&gt;    &lt;span style="color: darkcyan;"&gt;$self&lt;/span&gt;&lt;span style="color: darkcyan;"&gt;-&amp;gt;y&lt;/span&gt;( &lt;span style="color: darkcyan;"&gt;$self&lt;/span&gt;&lt;span style="color: darkcyan;"&gt;-&amp;gt;y&lt;/span&gt; + &lt;span style="color: darkcyan;"&gt;$y_delta&lt;/span&gt; );&lt;br /&gt;&lt;span style="color: brown;"&gt;27 &lt;/span&gt;}&lt;span style="color: brown;"&gt;&lt;/span&gt;&lt;/pre&gt;&lt;br /&gt;Como puedes ver, el manejo de los atributos es fastidioso, aquí es donde los rasgos comienzan a ser útiles, en particular las coordenadas de un punto tienen rasgos numéricos, veamos como mejora el código cuando los aplicamos:&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;span style="color: brown;"&gt; 1 &lt;/span&gt;&lt;span style="color: brown;"&gt;&lt;b&gt;package&lt;/b&gt;&lt;/span&gt;&lt;span style="color: seagreen;"&gt;&lt;b&gt; Point;&lt;/b&gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="color: brown;"&gt; 2 &lt;/span&gt;&lt;span style="color: #a020f0;"&gt;use &lt;/span&gt;Moose;&lt;br /&gt;&lt;span style="color: brown;"&gt; 3 &lt;/span&gt;&lt;br /&gt;&lt;span style="color: brown;"&gt; 4 &lt;/span&gt;has &lt;span style="color: magenta;"&gt;'&lt;/span&gt;&lt;span style="color: magenta;"&gt;x&lt;/span&gt;&lt;span style="color: magenta;"&gt;'&lt;/span&gt; =&amp;gt; (&lt;br /&gt;&lt;span style="color: brown;"&gt; 5 &lt;/span&gt;    &lt;span style="color: magenta;"&gt;traits  &lt;/span&gt;=&amp;gt; [&lt;span style="color: magenta;"&gt;"&lt;/span&gt;&lt;span style="color: magenta;"&gt;Number&lt;/span&gt;&lt;span style="color: magenta;"&gt;"&lt;/span&gt;],&lt;br /&gt;&lt;span style="color: brown;"&gt; 6 &lt;/span&gt;    &lt;span style="color: magenta;"&gt;is      &lt;/span&gt;=&amp;gt; &lt;span style="color: magenta;"&gt;'&lt;/span&gt;&lt;span style="color: magenta;"&gt;rw&lt;/span&gt;&lt;span style="color: magenta;"&gt;'&lt;/span&gt;,&lt;br /&gt;&lt;span style="color: brown;"&gt; 7 &lt;/span&gt;    &lt;span style="color: magenta;"&gt;isa     &lt;/span&gt;=&amp;gt; &lt;span style="color: magenta;"&gt;'&lt;/span&gt;&lt;span style="color: magenta;"&gt;Int&lt;/span&gt;&lt;span style="color: magenta;"&gt;'&lt;/span&gt;,&lt;br /&gt;&lt;span style="color: brown;"&gt; 8 &lt;/span&gt;    &lt;span style="color: magenta;"&gt;default &lt;/span&gt;=&amp;gt; &lt;span style="color: magenta;"&gt;0&lt;/span&gt;,&lt;br /&gt;&lt;span style="color: brown;"&gt; 9 &lt;/span&gt;    &lt;span style="color: magenta;"&gt;handles &lt;/span&gt;=&amp;gt; { &lt;span style="color: magenta;"&gt;translate_x &lt;/span&gt;=&amp;gt; &lt;span style="color: magenta;"&gt;"&lt;/span&gt;&lt;span style="color: magenta;"&gt;add&lt;/span&gt;&lt;span style="color: magenta;"&gt;"&lt;/span&gt;, }&lt;br /&gt;&lt;span style="color: brown;"&gt;10 &lt;/span&gt;);&lt;br /&gt;&lt;span style="color: brown;"&gt;11 &lt;/span&gt;&lt;br /&gt;&lt;span style="color: brown;"&gt;12 &lt;/span&gt;has &lt;span style="color: magenta;"&gt;'&lt;/span&gt;&lt;span style="color: magenta;"&gt;y&lt;/span&gt;&lt;span style="color: magenta;"&gt;'&lt;/span&gt; =&amp;gt; (&lt;br /&gt;&lt;span style="color: brown;"&gt;13 &lt;/span&gt;    &lt;span style="color: magenta;"&gt;traits  &lt;/span&gt;=&amp;gt; [&lt;span style="color: magenta;"&gt;"&lt;/span&gt;&lt;span style="color: magenta;"&gt;Number&lt;/span&gt;&lt;span style="color: magenta;"&gt;"&lt;/span&gt;],&lt;br /&gt;&lt;span style="color: brown;"&gt;14 &lt;/span&gt;    &lt;span style="color: magenta;"&gt;is      &lt;/span&gt;=&amp;gt; &lt;span style="color: magenta;"&gt;'&lt;/span&gt;&lt;span style="color: magenta;"&gt;rw&lt;/span&gt;&lt;span style="color: magenta;"&gt;'&lt;/span&gt;,&lt;br /&gt;&lt;span style="color: brown;"&gt;15 &lt;/span&gt;    &lt;span style="color: magenta;"&gt;isa     &lt;/span&gt;=&amp;gt; &lt;span style="color: magenta;"&gt;'&lt;/span&gt;&lt;span style="color: magenta;"&gt;Int&lt;/span&gt;&lt;span style="color: magenta;"&gt;'&lt;/span&gt;,&lt;br /&gt;&lt;span style="color: brown;"&gt;16 &lt;/span&gt;    &lt;span style="color: magenta;"&gt;default &lt;/span&gt;=&amp;gt; &lt;span style="color: magenta;"&gt;0&lt;/span&gt;,&lt;br /&gt;&lt;span style="color: brown;"&gt;17 &lt;/span&gt;    &lt;span style="color: magenta;"&gt;handles &lt;/span&gt;=&amp;gt; { &lt;span style="color: magenta;"&gt;translate_y &lt;/span&gt;=&amp;gt; &lt;span style="color: magenta;"&gt;"&lt;/span&gt;&lt;span style="color: magenta;"&gt;add&lt;/span&gt;&lt;span style="color: magenta;"&gt;"&lt;/span&gt;, }&lt;br /&gt;&lt;span style="color: brown;"&gt;18 &lt;/span&gt;);&lt;br /&gt;&lt;span style="color: brown;"&gt;19 &lt;/span&gt;&lt;br /&gt;&lt;span style="color: brown;"&gt;20 &lt;/span&gt;&lt;span style="color: brown;"&gt;&lt;b&gt;sub&lt;/b&gt;&lt;/span&gt;&lt;span style="color: darkcyan;"&gt; &lt;/span&gt;&lt;span style="color: darkcyan;"&gt;clear &lt;/span&gt;{&lt;br /&gt;&lt;span style="color: brown;"&gt;21 &lt;/span&gt;    &lt;span style="color: brown;"&gt;&lt;b&gt;my&lt;/b&gt;&lt;/span&gt; &lt;span style="color: darkcyan;"&gt;$self&lt;/span&gt; = &lt;span style="color: brown;"&gt;&lt;b&gt;shift&lt;/b&gt;&lt;/span&gt;;&lt;br /&gt;&lt;span style="color: brown;"&gt;22 &lt;/span&gt;    &lt;span style="color: darkcyan;"&gt;$self&lt;/span&gt;&lt;span style="color: darkcyan;"&gt;-&amp;gt;x&lt;/span&gt;(&lt;span style="color: magenta;"&gt;0&lt;/span&gt;);&lt;br /&gt;&lt;span style="color: brown;"&gt;23 &lt;/span&gt;    &lt;span style="color: darkcyan;"&gt;$self&lt;/span&gt;&lt;span style="color: darkcyan;"&gt;-&amp;gt;y&lt;/span&gt;(&lt;span style="color: magenta;"&gt;0&lt;/span&gt;);&lt;br /&gt;&lt;span style="color: brown;"&gt;24 &lt;/span&gt;}&lt;br /&gt;&lt;span style="color: brown;"&gt;25 &lt;/span&gt;&lt;br /&gt;&lt;span style="color: brown;"&gt;26 &lt;/span&gt;&lt;span style="color: brown;"&gt;&lt;b&gt;sub&lt;/b&gt;&lt;/span&gt;&lt;span style="color: darkcyan;"&gt; &lt;/span&gt;&lt;span style="color: darkcyan;"&gt;distance_sqr &lt;/span&gt;{&lt;br /&gt;&lt;span style="color: brown;"&gt;27 &lt;/span&gt;    &lt;span style="color: brown;"&gt;&lt;b&gt;my&lt;/b&gt;&lt;/span&gt; ( &lt;span style="color: darkcyan;"&gt;$self&lt;/span&gt;, &lt;span style="color: darkcyan;"&gt;$point&lt;/span&gt; ) = &lt;span style="color: darkcyan;"&gt;@_&lt;/span&gt;;&lt;br /&gt;&lt;span style="color: brown;"&gt;28 &lt;/span&gt;    &lt;span style="color: brown;"&gt;&lt;b&gt;return&lt;/b&gt;&lt;/span&gt; ( &lt;span style="color: darkcyan;"&gt;$self&lt;/span&gt;&lt;span style="color: darkcyan;"&gt;-&amp;gt;x&lt;/span&gt; - &lt;span style="color: darkcyan;"&gt;$point&lt;/span&gt;&lt;span style="color: darkcyan;"&gt;-&amp;gt;x&lt;/span&gt; )**&lt;span style="color: magenta;"&gt;2&lt;/span&gt; + ( &lt;span style="color: darkcyan;"&gt;$self&lt;/span&gt;&lt;span style="color: darkcyan;"&gt;-&amp;gt;y&lt;/span&gt; - &lt;span style="color: darkcyan;"&gt;$point&lt;/span&gt;&lt;span style="color: darkcyan;"&gt;-&amp;gt;y&lt;/span&gt; )**&lt;span style="color: magenta;"&gt;2&lt;/span&gt;;&lt;br /&gt;&lt;span style="color: brown;"&gt;29 &lt;/span&gt;}&lt;br /&gt;&lt;span style="color: brown;"&gt;30 &lt;/span&gt;&lt;br /&gt;&lt;span style="color: brown;"&gt;31 &lt;/span&gt;&lt;span style="color: brown;"&gt;&lt;b&gt;sub&lt;/b&gt;&lt;/span&gt;&lt;span style="color: darkcyan;"&gt; &lt;/span&gt;&lt;span style="color: darkcyan;"&gt;distance &lt;/span&gt;{&lt;br /&gt;&lt;span style="color: brown;"&gt;32 &lt;/span&gt;    &lt;span style="color: brown;"&gt;&lt;b&gt;my&lt;/b&gt;&lt;/span&gt; ( &lt;span style="color: darkcyan;"&gt;$self&lt;/span&gt;, &lt;span style="color: darkcyan;"&gt;$point&lt;/span&gt; ) = &lt;span style="color: darkcyan;"&gt;@_&lt;/span&gt;;&lt;br /&gt;&lt;span style="color: brown;"&gt;33 &lt;/span&gt;    &lt;span style="color: brown;"&gt;&lt;b&gt;return&lt;/b&gt;&lt;/span&gt; &lt;span style="color: brown;"&gt;&lt;b&gt;sqrt&lt;/b&gt;&lt;/span&gt; &lt;span style="color: darkcyan;"&gt;$self&lt;/span&gt;&lt;span style="color: darkcyan;"&gt;-&amp;gt;distance_sqr&lt;/span&gt;(&lt;span style="color: darkcyan;"&gt;$point&lt;/span&gt;);&lt;br /&gt;&lt;span style="color: brown;"&gt;34 &lt;/span&gt;}&lt;br /&gt;&lt;span style="color: brown;"&gt;35 &lt;/span&gt;&lt;br /&gt;&lt;span style="color: brown;"&gt;36 &lt;/span&gt;&lt;span style="color: brown;"&gt;&lt;b&gt;sub&lt;/b&gt;&lt;/span&gt;&lt;span style="color: darkcyan;"&gt; &lt;/span&gt;&lt;span style="color: darkcyan;"&gt;translate &lt;/span&gt;{&lt;br /&gt;&lt;span style="color: brown;"&gt;37 &lt;/span&gt;    &lt;span style="color: brown;"&gt;&lt;b&gt;my&lt;/b&gt;&lt;/span&gt; ( &lt;span style="color: darkcyan;"&gt;$self&lt;/span&gt;, &lt;span style="color: darkcyan;"&gt;$x_delta&lt;/span&gt;, &lt;span style="color: darkcyan;"&gt;$y_delta&lt;/span&gt; ) = &lt;span style="color: darkcyan;"&gt;@_&lt;/span&gt;;&lt;br /&gt;&lt;span style="color: brown;"&gt;38 &lt;/span&gt;    &lt;span style="color: darkcyan;"&gt;$self&lt;/span&gt;&lt;span style="color: darkcyan;"&gt;-&amp;gt;translate_x&lt;/span&gt;( &lt;span style="color: darkcyan;"&gt;$x_delta&lt;/span&gt; );&lt;br /&gt;&lt;span style="color: brown;"&gt;39 &lt;/span&gt;    &lt;span style="color: darkcyan;"&gt;$self&lt;/span&gt;&lt;span style="color: darkcyan;"&gt;-&amp;gt;translate_y&lt;/span&gt;( &lt;span style="color: darkcyan;"&gt;$y_delta&lt;/span&gt; );&lt;br /&gt;&lt;span style="color: brown;"&gt;40 &lt;/span&gt;}&lt;br /&gt;&lt;span style="color: brown;"&gt;41 &lt;/span&gt;&lt;br /&gt;&lt;span style="color: brown;"&gt;42 &lt;/span&gt;&lt;span style="color: magenta;"&gt;1&lt;/span&gt;;&lt;br /&gt;&lt;span style="color: brown;"&gt;&lt;/span&gt;&lt;/pre&gt;&lt;br /&gt;Las líneas 5 y 13 declaran los rasgos (traits) del atributo, es una arreglo porque se pueden agregar tantos rasgos como quieras a un mismo atributo. Las líneas 9 y 17 generan métodos en la clase para representar el comportamiento del rasgo en el objeto, por ejemplo en la línea 9 se define translate_x como el método que implementa la operación add sobre el atributo x. &lt;br /&gt;&lt;br /&gt;El rasgo "Number" provee métodos como add, sub, set y otros que puedes consultar en &lt;a href="http://search.cpan.org/perldoc?Moose::Meta::Attribute::Native::Trait::Number"&gt;Moose::Meta::Attribute::Native::Trait::Number&lt;/a&gt;, que es la clase que los hace disponibles en Moose.&lt;br /&gt;&lt;br /&gt;El uso de rasgos no solamente es cómodo, también es más eficiente que utilizar directamente los accesors, en el primer ejemplo se accede al valor de una coordenada, que se suma y se accede nuevamente (para escribirla), en el segundo caso translate_x suma directamente el argumento al atributo.&lt;br /&gt;&lt;br /&gt;Estas diferencias se pueden hace más notorias si usamos tipos de datos más complejos, por ejemplo en el caso de las cadenas de caracteres una modificación mediante un accessor puede resultar muy costosa, supongamos un cadena de caracteres:&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;span style="color: brown;"&gt;1 &lt;/span&gt;has &lt;span style="color: magenta;"&gt;text &lt;/span&gt;=&amp;gt; (&lt;span style="color: magenta;"&gt;is &lt;/span&gt;=&amp;gt; &lt;span style="color: magenta;"&gt;"&lt;/span&gt;&lt;span style="color: magenta;"&gt;rw&lt;/span&gt;&lt;span style="color: magenta;"&gt;"&lt;/span&gt;, &lt;span style="color: magenta;"&gt;isa &lt;/span&gt;=&amp;gt; &lt;span style="color: magenta;"&gt;"&lt;/span&gt;&lt;span style="color: magenta;"&gt;Str&lt;/span&gt;&lt;span style="color: magenta;"&gt;"&lt;/span&gt;);&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;Si queremos afectar la cadena, digamos haciendo una substitución:&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;span style="color: brown;"&gt;1 &lt;/span&gt;&lt;span style="color: brown;"&gt;&lt;b&gt;my&lt;/b&gt;&lt;/span&gt; &lt;span style="color: darkcyan;"&gt;$temp&lt;/span&gt; = &lt;span style="color: darkcyan;"&gt;$self&lt;/span&gt;&lt;span style="color: darkcyan;"&gt;-&amp;gt;text&lt;/span&gt;;&lt;br /&gt;&lt;span style="color: brown;"&gt;2 &lt;/span&gt;&lt;span style="color: darkcyan;"&gt;$temp&lt;/span&gt; =~ &lt;span style="color: brown;"&gt;&lt;b&gt;s/&lt;/b&gt;&lt;/span&gt;&lt;span style="color: magenta;"&gt;java&lt;/span&gt;&lt;span style="color: brown;"&gt;&lt;b&gt;/&lt;/b&gt;&lt;/span&gt;&lt;span style="color: magenta;"&gt;perl&lt;/span&gt;&lt;span style="color: brown;"&gt;&lt;b&gt;/&lt;/b&gt;&lt;/span&gt;;&lt;br /&gt;&lt;span style="color: brown;"&gt;3 &lt;/span&gt;&lt;span style="color: darkcyan;"&gt;$self&lt;/span&gt;&lt;span style="color: darkcyan;"&gt;-&amp;gt;text&lt;/span&gt;(&lt;span style="color: darkcyan;"&gt;$temp&lt;/span&gt;);&lt;span style="color: brown;"&gt;&lt;/span&gt;&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;Esto además de ser incomodo, poco claro y realmente feo (hasta parece Java), puede llegar a ser bastante ineficiente, sobre todo si las cadenas son largas, pues se estan copiando dos veces (cuando se obtienen y cuando se guardan).&lt;br /&gt;&lt;br /&gt;En este caso se puede declarar el atributo con un rasgo "String" y usar la operación "replace":&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;span style="color: brown;"&gt; 1 &lt;/span&gt;has &lt;span style="color: magenta;"&gt;'&lt;/span&gt;&lt;span style="color: magenta;"&gt;text&lt;/span&gt;&lt;span style="color: magenta;"&gt;'&lt;/span&gt; =&amp;gt; (&lt;br /&gt;&lt;span style="color: brown;"&gt; 2 &lt;/span&gt;    &lt;span style="color: magenta;"&gt;traits  &lt;/span&gt;=&amp;gt; [&lt;span style="color: magenta;"&gt;'&lt;/span&gt;&lt;span style="color: magenta;"&gt;String&lt;/span&gt;&lt;span style="color: magenta;"&gt;'&lt;/span&gt;],&lt;br /&gt;&lt;span style="color: brown;"&gt; 3 &lt;/span&gt;    &lt;span style="color: magenta;"&gt;is      &lt;/span&gt;=&amp;gt; &lt;span style="color: magenta;"&gt;'&lt;/span&gt;&lt;span style="color: magenta;"&gt;rw&lt;/span&gt;&lt;span style="color: magenta;"&gt;'&lt;/span&gt;,&lt;br /&gt;&lt;span style="color: brown;"&gt; 4 &lt;/span&gt;    &lt;span style="color: magenta;"&gt;isa     &lt;/span&gt;=&amp;gt; &lt;span style="color: magenta;"&gt;'&lt;/span&gt;&lt;span style="color: magenta;"&gt;Str&lt;/span&gt;&lt;span style="color: magenta;"&gt;'&lt;/span&gt;,&lt;br /&gt;&lt;span style="color: brown;"&gt; 5 &lt;/span&gt;    &lt;span style="color: magenta;"&gt;default &lt;/span&gt;=&amp;gt; &lt;span style="color: magenta;"&gt;q{}&lt;/span&gt;,&lt;br /&gt;&lt;span style="color: brown;"&gt; 6 &lt;/span&gt;    &lt;span style="color: magenta;"&gt;handles &lt;/span&gt;=&amp;gt; {&lt;br /&gt;&lt;span style="color: brown;"&gt; 7 &lt;/span&gt;        &lt;span style="color: magenta;"&gt;replace_text &lt;/span&gt;=&amp;gt; &lt;span style="color: magenta;"&gt;'&lt;/span&gt;&lt;span style="color: magenta;"&gt;replace&lt;/span&gt;&lt;span style="color: magenta;"&gt;'&lt;/span&gt;,&lt;br /&gt;&lt;span style="color: brown;"&gt; 8 &lt;/span&gt;    },&lt;br /&gt;&lt;span style="color: brown;"&gt; 9 &lt;/span&gt;);&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;y luego la usas así:&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;span style="color: brown;"&gt;&lt;/span&gt;&lt;span style="color: brown;"&gt;11 &lt;/span&gt;&lt;span style="color: darkcyan;"&gt;$self&lt;/span&gt;&lt;span style="color: darkcyan;"&gt;-&amp;gt;replace_text&lt;/span&gt;( &lt;span style="color: magenta;"&gt;qr/&lt;/span&gt;&lt;span style="color: magenta;"&gt;java&lt;/span&gt;&lt;span style="color: magenta;"&gt;/&lt;/span&gt;, &lt;span style="color: magenta;"&gt;"&lt;/span&gt;&lt;span style="color: magenta;"&gt;perl&lt;/span&gt;&lt;span style="color: magenta;"&gt;"&lt;/span&gt; );&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;Cuando se usan arreglos y hashes los rasgos son realmente muy útiles, y lo mejor es que además te puedes hacer tus propios rasgos, aunque esto será para otro artículo.&lt;br /&gt;&lt;br /&gt;Por ahora puedes ver los rasgos que ofrece Moose para los tipos de datos nativos de Perl leyendo la documentación de: &lt;a href="http://search.cpan.org/perldoc?Moose::Meta::Attribute::Native"&gt;Moose::Meta::Attribute::Native&lt;/a&gt;. Puede que consigas código donde se implementan los rasgos utilizando: MooseX::AttributeHelpers, sin embargo es mucho mejor (y más fácil) usar &lt;a href="http://search.cpan.org/perldoc?Moose::Meta::Attribute::Native"&gt;Moose::Meta::Attribute::Native&lt;/a&gt; que ahora es parte de Moose.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5238463735728501931-5654221123234274523?l=perliscopio.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://perliscopio.blogspot.com/feeds/5654221123234274523/comments/default' title='Enviar comentarios'/><link rel='replies' type='text/html' href='http://perliscopio.blogspot.com/2010/01/atributos-con-rasgos-en-moose.html#comment-form' title='0 comentarios'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5238463735728501931/posts/default/5654221123234274523'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5238463735728501931/posts/default/5654221123234274523'/><link rel='alternate' type='text/html' href='http://perliscopio.blogspot.com/2010/01/atributos-con-rasgos-en-moose.html' title='Atributos con rasgos en Moose.'/><author><name>Jose Rey</name><uri>http://www.blogger.com/profile/15071755167581242815</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5238463735728501931.post-5806421058337246937</id><published>2009-12-24T02:26:00.006-04:30</published><updated>2010-01-11T00:47:54.949-04:30</updated><category scheme='http://www.blogger.com/atom/ns#' term='Tutorial'/><category scheme='http://www.blogger.com/atom/ns#' term='Perl'/><category scheme='http://www.blogger.com/atom/ns#' term='CPAN'/><category scheme='http://www.blogger.com/atom/ns#' term='Moose'/><title type='text'>Conociendo al alce (Moose)</title><content type='html'>En otras ocasiones les he hablado de de &lt;a href="http://search.cpan.org/perldoc?Moose"&gt;Moose&lt;/a&gt;, hoy voy a explicar lo más básico de este nuevo sistema de programación orientada a objetos que ha tomado por asalto al CPAN y que muchos desarrollos están adoptando como plataforma oficial de programación orientada a objetos.&lt;br /&gt;&lt;br /&gt;Todo este ruido es porque &lt;a href="http://search.cpan.org/perldoc?Moose"&gt;Moose&lt;/a&gt; ofece mecanismos únicos de reutilización de código y polimorfismo que además son muy fáciles de utilizar. Así que ahora además de la herencia podrás utilizar roles (también conocidos como mixins), tendrás la capacidad de alterar fácilmente el comportamiento de una clase desde un rol, podrás delegar la de una clase en otra de manerá mágica, establecer contratos, inicialización perezosa, verificación de tipos y docenas de nuevas características que te harán reflexionar sobre como has podido programar toda tu vida sin ellas.&lt;br /&gt;&lt;br /&gt;Directo del manual de &lt;a href="http://search.cpan.org/perldoc?Moose"&gt;Moose&lt;/a&gt; un ejemplo sencillo de implementación de herencia:&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;span style="color: brown;"&gt; 1 &lt;/span&gt;&lt;span style="color: brown;"&gt;&lt;b&gt;package&lt;/b&gt;&lt;/span&gt;&lt;span style="color: seagreen;"&gt;&lt;b&gt; Point;&lt;/b&gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="color: brown;"&gt; 2 &lt;/span&gt;&lt;span style="color: #a020f0;"&gt;use &lt;/span&gt;Moose;&lt;br /&gt;&lt;span style="color: brown;"&gt; 3 &lt;/span&gt;&lt;br /&gt;&lt;span style="color: brown;"&gt; 4 &lt;/span&gt;has &lt;span style="color: magenta;"&gt;'&lt;/span&gt;&lt;span style="color: magenta;"&gt;x&lt;/span&gt;&lt;span style="color: magenta;"&gt;'&lt;/span&gt; =&amp;gt; ( &lt;span style="color: magenta;"&gt;is &lt;/span&gt;=&amp;gt; &lt;span style="color: magenta;"&gt;'&lt;/span&gt;&lt;span style="color: magenta;"&gt;rw&lt;/span&gt;&lt;span style="color: magenta;"&gt;'&lt;/span&gt;, &lt;span style="color: magenta;"&gt;isa &lt;/span&gt;=&amp;gt; &lt;span style="color: magenta;"&gt;'&lt;/span&gt;&lt;span style="color: magenta;"&gt;Int&lt;/span&gt;&lt;span style="color: magenta;"&gt;'&lt;/span&gt;, &lt;span style="color: magenta;"&gt;default &lt;/span&gt;=&amp;gt; &lt;span style="color: magenta;"&gt;0&lt;/span&gt; );&lt;br /&gt;&lt;span style="color: brown;"&gt; 5 &lt;/span&gt;has &lt;span style="color: magenta;"&gt;'&lt;/span&gt;&lt;span style="color: magenta;"&gt;y&lt;/span&gt;&lt;span style="color: magenta;"&gt;'&lt;/span&gt; =&amp;gt; ( &lt;span style="color: magenta;"&gt;is &lt;/span&gt;=&amp;gt; &lt;span style="color: magenta;"&gt;'&lt;/span&gt;&lt;span style="color: magenta;"&gt;rw&lt;/span&gt;&lt;span style="color: magenta;"&gt;'&lt;/span&gt;, &lt;span style="color: magenta;"&gt;isa &lt;/span&gt;=&amp;gt; &lt;span style="color: magenta;"&gt;'&lt;/span&gt;&lt;span style="color: magenta;"&gt;Int&lt;/span&gt;&lt;span style="color: magenta;"&gt;'&lt;/span&gt;, &lt;span style="color: magenta;"&gt;default &lt;/span&gt;=&amp;gt; &lt;span style="color: magenta;"&gt;0&lt;/span&gt; );&lt;br /&gt;&lt;span style="color: brown;"&gt; 6 &lt;/span&gt;&lt;br /&gt;&lt;span style="color: brown;"&gt; 7 &lt;/span&gt;&lt;span style="color: brown;"&gt;&lt;b&gt;sub&lt;/b&gt;&lt;/span&gt;&lt;span style="color: darkcyan;"&gt; &lt;/span&gt;&lt;span style="color: darkcyan;"&gt;clear &lt;/span&gt;{&lt;br /&gt;&lt;span style="color: brown;"&gt; 8 &lt;/span&gt;    &lt;span style="color: brown;"&gt;&lt;b&gt;my&lt;/b&gt;&lt;/span&gt; &lt;span style="color: darkcyan;"&gt;$self&lt;/span&gt; = &lt;span style="color: brown;"&gt;&lt;b&gt;shift&lt;/b&gt;&lt;/span&gt;;&lt;br /&gt;&lt;span style="color: brown;"&gt; 9 &lt;/span&gt;    &lt;span style="color: darkcyan;"&gt;$self&lt;/span&gt;&lt;span style="color: darkcyan;"&gt;-&amp;gt;x&lt;/span&gt;(&lt;span style="color: magenta;"&gt;0&lt;/span&gt;);&lt;br /&gt;&lt;span style="color: brown;"&gt;10 &lt;/span&gt;    &lt;span style="color: darkcyan;"&gt;$self&lt;/span&gt;&lt;span style="color: darkcyan;"&gt;-&amp;gt;y&lt;/span&gt;(&lt;span style="color: magenta;"&gt;0&lt;/span&gt;);&lt;br /&gt;&lt;span style="color: brown;"&gt;11 &lt;/span&gt;}&lt;br /&gt;&lt;span style="color: brown;"&gt;12 &lt;/span&gt;&lt;br /&gt;&lt;span style="color: brown;"&gt;13 &lt;/span&gt;&lt;span style="color: brown;"&gt;&lt;b&gt;sub&lt;/b&gt;&lt;/span&gt;&lt;span style="color: darkcyan;"&gt; &lt;/span&gt;&lt;span style="color: darkcyan;"&gt;distance_sqr &lt;/span&gt;{&lt;br /&gt;&lt;span style="color: brown;"&gt;14 &lt;/span&gt;    &lt;span style="color: brown;"&gt;&lt;b&gt;my&lt;/b&gt;&lt;/span&gt; (&lt;span style="color: darkcyan;"&gt;$self&lt;/span&gt;, &lt;span style="color: darkcyan;"&gt;$point&lt;/span&gt;) = &lt;span style="color: darkcyan;"&gt;@_&lt;/span&gt;;&lt;br /&gt;&lt;span style="color: brown;"&gt;15 &lt;/span&gt;    &lt;span style="color: brown;"&gt;&lt;b&gt;return&lt;/b&gt;&lt;/span&gt; (&lt;span style="color: darkcyan;"&gt;$self&lt;/span&gt;&lt;span style="color: darkcyan;"&gt;-&amp;gt;x&lt;/span&gt; - &lt;span style="color: darkcyan;"&gt;$point&lt;/span&gt;&lt;span style="color: darkcyan;"&gt;-&amp;gt;x&lt;/span&gt;)**&lt;span style="color: magenta;"&gt;2&lt;/span&gt; + (&lt;span style="color: darkcyan;"&gt;$self&lt;/span&gt;&lt;span style="color: darkcyan;"&gt;-&amp;gt;y&lt;/span&gt; - &lt;span style="color: darkcyan;"&gt;$point&lt;/span&gt;&lt;span style="color: darkcyan;"&gt;-&amp;gt;y&lt;/span&gt;)**&lt;span style="color: magenta;"&gt;2&lt;/span&gt;;&lt;br /&gt;&lt;span style="color: brown;"&gt;16 &lt;/span&gt;}&lt;br /&gt;&lt;span style="color: brown;"&gt;17 &lt;/span&gt;&lt;br /&gt;&lt;span style="color: brown;"&gt;18 &lt;/span&gt;&lt;span style="color: brown;"&gt;&lt;b&gt;sub&lt;/b&gt;&lt;/span&gt;&lt;span style="color: darkcyan;"&gt; &lt;/span&gt;&lt;span style="color: darkcyan;"&gt;distance &lt;/span&gt;{&lt;br /&gt;&lt;span style="color: brown;"&gt;19 &lt;/span&gt;    &lt;span style="color: brown;"&gt;&lt;b&gt;my&lt;/b&gt;&lt;/span&gt; (&lt;span style="color: darkcyan;"&gt;$self&lt;/span&gt;, &lt;span style="color: darkcyan;"&gt;$point&lt;/span&gt;) = &lt;span style="color: darkcyan;"&gt;@_&lt;/span&gt;;&lt;br /&gt;&lt;span style="color: brown;"&gt;20 &lt;/span&gt;    &lt;span style="color: brown;"&gt;&lt;b&gt;return&lt;/b&gt;&lt;/span&gt; &lt;span style="color: brown;"&gt;&lt;b&gt;sqrt&lt;/b&gt;&lt;/span&gt; &lt;span style="color: darkcyan;"&gt;$self&lt;/span&gt;&lt;span style="color: darkcyan;"&gt;-&amp;gt;distance_sqr&lt;/span&gt;( &lt;span style="color: darkcyan;"&gt;$point&lt;/span&gt; );&lt;br /&gt;&lt;span style="color: brown;"&gt;21 &lt;/span&gt;}&lt;br /&gt;&lt;span style="color: brown;"&gt;22 &lt;/span&gt;&lt;br /&gt;&lt;span style="color: brown;"&gt;23 &lt;/span&gt;&lt;span style="color: magenta;"&gt;1&lt;/span&gt;;&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;La línea 2 usa &lt;a href="http://search.cpan.org/perldoc?Moose"&gt;Moose&lt;/a&gt;, lo que ejecuta un compilador que transforma el programa, y que de paso activa el modo estricto (use strict) y las advertencias (use warnings).&lt;br /&gt;&lt;br /&gt;Luego decimos que nuestro objeto tiene dos atributos (líneas 4 y 5) llamados &lt;code&gt;&lt;span style="color: magenta;"&gt;x&lt;/span&gt;&lt;/code&gt; y &lt;code&gt;&lt;span style="color: magenta;"&gt;y&lt;/span&gt;&lt;/code&gt;, estos atributos permiten la escritura y la lectura (is =&amp;gt; "rw") y son de enteros (isa =&amp;gt; "Int") y tienen un valor por defecto de 0 (default =&amp;gt; 0), estas dos líneas generan los métodos de acceso a los atributos que además verifican la validez de los datos que se asignen a dichos atributos, también crean el código necesario para incializar los valores de los atributos en 0.&lt;br /&gt;&lt;br /&gt;Luego se implementa una operación que borra el punto, es decir lo pone en (0,0) y otros que calculan la distancia y la distancia al cuadrado de este punto a otro.&lt;br /&gt;&lt;br /&gt;Hasta ahora, puede parecer que &lt;a href="http://search.cpan.org/perldoc?Moose"&gt;Moose&lt;/a&gt; ahorra trabajo, sin embargo, siguiendo con el ejemplo veamos como sería un punto en 3 dimensiones:&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;span style="color: brown;"&gt; 1 &lt;/span&gt;&lt;span style="color: brown;"&gt;&lt;b&gt;package&lt;/b&gt;&lt;/span&gt;&lt;span style="color: seagreen;"&gt;&lt;b&gt; Point3D;&lt;/b&gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="color: brown;"&gt; 2 &lt;/span&gt;&lt;span style="color: #a020f0;"&gt;use &lt;/span&gt;Moose;&lt;br /&gt;&lt;span style="color: brown;"&gt; 3 &lt;/span&gt;&lt;br /&gt;&lt;span style="color: brown;"&gt; 4 &lt;/span&gt;extends &lt;span style="color: magenta;"&gt;'&lt;/span&gt;&lt;span style="color: magenta;"&gt;Point&lt;/span&gt;&lt;span style="color: magenta;"&gt;'&lt;/span&gt;;&lt;br /&gt;&lt;span style="color: brown;"&gt; 5 &lt;/span&gt;&lt;br /&gt;&lt;span style="color: brown;"&gt; 6 &lt;/span&gt;has &lt;span style="color: magenta;"&gt;'&lt;/span&gt;&lt;span style="color: magenta;"&gt;z&lt;/span&gt;&lt;span style="color: magenta;"&gt;'&lt;/span&gt; =&amp;gt; ( &lt;span style="color: magenta;"&gt;is &lt;/span&gt;=&amp;gt; &lt;span style="color: magenta;"&gt;'&lt;/span&gt;&lt;span style="color: magenta;"&gt;rw&lt;/span&gt;&lt;span style="color: magenta;"&gt;'&lt;/span&gt;, &lt;span style="color: magenta;"&gt;isa &lt;/span&gt;=&amp;gt; &lt;span style="color: magenta;"&gt;'&lt;/span&gt;&lt;span style="color: magenta;"&gt;Int&lt;/span&gt;&lt;span style="color: magenta;"&gt;'&lt;/span&gt;, &lt;span style="color: magenta;"&gt;default &lt;/span&gt;=&amp;gt; &lt;span style="color: magenta;"&gt;0&lt;/span&gt; );&lt;br /&gt;&lt;span style="color: brown;"&gt; 7 &lt;/span&gt;&lt;br /&gt;&lt;span style="color: brown;"&gt; 8 &lt;/span&gt;after &lt;span style="color: magenta;"&gt;'&lt;/span&gt;&lt;span style="color: magenta;"&gt;clear&lt;/span&gt;&lt;span style="color: magenta;"&gt;'&lt;/span&gt; =&amp;gt;&lt;span style="color: darkcyan;"&gt; &lt;/span&gt;&lt;span style="color: brown;"&gt;&lt;b&gt;sub&lt;/b&gt;&lt;/span&gt;&lt;span style="color: darkcyan;"&gt; &lt;/span&gt;{&lt;br /&gt;&lt;span style="color: brown;"&gt; 9 &lt;/span&gt;    &lt;span style="color: brown;"&gt;&lt;b&gt;my&lt;/b&gt;&lt;/span&gt; &lt;span style="color: darkcyan;"&gt;$self&lt;/span&gt; = &lt;span style="color: brown;"&gt;&lt;b&gt;shift&lt;/b&gt;&lt;/span&gt;;&lt;br /&gt;&lt;span style="color: brown;"&gt;10 &lt;/span&gt;    &lt;span style="color: darkcyan;"&gt;$self&lt;/span&gt;&lt;span style="color: darkcyan;"&gt;-&amp;gt;z&lt;/span&gt;(&lt;span style="color: magenta;"&gt;0&lt;/span&gt;);&lt;br /&gt;&lt;span style="color: brown;"&gt;11 &lt;/span&gt;};&lt;br /&gt;&lt;span style="color: brown;"&gt;12 &lt;/span&gt;&lt;br /&gt;&lt;span style="color: brown;"&gt;13 &lt;/span&gt;around &lt;span style="color: magenta;"&gt;'&lt;/span&gt;&lt;span style="color: magenta;"&gt;distance_sqr&lt;/span&gt;&lt;span style="color: magenta;"&gt;'&lt;/span&gt; =&amp;gt;&lt;span style="color: darkcyan;"&gt; &lt;/span&gt;&lt;span style="color: brown;"&gt;&lt;b&gt;sub&lt;/b&gt;&lt;/span&gt;&lt;span style="color: darkcyan;"&gt; &lt;/span&gt;{&lt;br /&gt;&lt;span style="color: brown;"&gt;14 &lt;/span&gt;    &lt;span style="color: brown;"&gt;&lt;b&gt;my&lt;/b&gt;&lt;/span&gt; (&lt;span style="color: darkcyan;"&gt;$orig&lt;/span&gt;, &lt;span style="color: darkcyan;"&gt;$self&lt;/span&gt;, &lt;span style="color: darkcyan;"&gt;$point&lt;/span&gt;) = &lt;span style="color: darkcyan;"&gt;@_&lt;/span&gt;;&lt;br /&gt;&lt;span style="color: brown;"&gt;15 &lt;/span&gt;    &lt;span style="color: brown;"&gt;&lt;b&gt;return&lt;/b&gt;&lt;/span&gt;  &lt;span style="color: darkcyan;"&gt;$self&lt;/span&gt;-&amp;gt;&lt;span style="color: darkcyan;"&gt;$orig&lt;/span&gt;(&lt;span style="color: darkcyan;"&gt;$point&lt;/span&gt;) + (&lt;span style="color: darkcyan;"&gt;$self&lt;/span&gt;&lt;span style="color: darkcyan;"&gt;-&amp;gt;z&lt;/span&gt; - &lt;span style="color: darkcyan;"&gt;$point&lt;/span&gt;&lt;span style="color: darkcyan;"&gt;-&amp;gt;z&lt;/span&gt;)**&lt;span style="color: magenta;"&gt;2&lt;/span&gt;;&lt;br /&gt;&lt;span style="color: brown;"&gt;16 &lt;/span&gt;};&lt;br /&gt;&lt;span style="color: brown;"&gt;17 &lt;/span&gt;&lt;br /&gt;&lt;span style="color: brown;"&gt;18 &lt;/span&gt;&lt;span style="color: magenta;"&gt;1&lt;/span&gt;;&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;Hacer una subclase es realmente simple solo se dice que esta clase extiende a otra (línea 4), se agrega un nuevo atributo y se agregan los métodos. Sin embargo Moose tiene interesantes capacidades que facilitan la reutilización del código, y es aquí donde se le empiza a ver el queso a la tostada.&lt;br /&gt;&lt;br /&gt;En vez de escribir un nuevo método &lt;code&gt;&lt;span style="color: magenta;"&gt;clear&lt;/span&gt;&lt;/code&gt; que sobreescriba el heredado, podemos agregarle un comportamiento al existente, así ni siquiera tenemos que invocar el método de la super clase.&lt;br /&gt;&lt;br /&gt;En el caso de &lt;code&gt;&lt;span style="color: magenta;"&gt;distance_sqr&lt;/span&gt;&lt;/code&gt; envolvemos el código de la super clase con nuestro método, lo que se parece un poco más a la manera tradicional de sobreescribir métodos para luego invocar al código de la super clase utilizando SUPER, sin embargo, estas operaciones le dan una gran potencia a un nuevo mecanismo de polimorfismo: los roles (también conocidos como mixins), del que hablaré en el próximo artículo.&lt;br /&gt;&lt;br /&gt;Los objetos creados con &lt;a href="http://search.cpan.org/perldoc?Moose"&gt;Moose&lt;/a&gt; se utilizan como cualquier otro objeto, tomando en cuenta que los parámetros del constructor ahora son estilo hash:&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;span style="color: brown;"&gt;1 &lt;/span&gt;&lt;span style="color: #a020f0;"&gt;use &lt;/span&gt;Point3D;&lt;br /&gt;&lt;span style="color: brown;"&gt;2 &lt;/span&gt;&lt;span style="color: #a020f0;"&gt;use &lt;/span&gt;Modern::Perl;&lt;br /&gt;&lt;span style="color: brown;"&gt;3 &lt;/span&gt;&lt;br /&gt;&lt;span style="color: brown;"&gt;4 &lt;/span&gt;&lt;span style="color: brown;"&gt;&lt;b&gt;my&lt;/b&gt;&lt;/span&gt; &lt;span style="color: darkcyan;"&gt;$p1&lt;/span&gt; = Point3D-&amp;gt;&lt;span style="color: brown;"&gt;&lt;b&gt;new&lt;/b&gt;&lt;/span&gt;;&lt;br /&gt;&lt;span style="color: brown;"&gt;5 &lt;/span&gt;&lt;span style="color: brown;"&gt;&lt;b&gt;my&lt;/b&gt;&lt;/span&gt; &lt;span style="color: darkcyan;"&gt;$p2&lt;/span&gt; = Point3D-&amp;gt;&lt;span style="color: brown;"&gt;&lt;b&gt;new&lt;/b&gt;&lt;/span&gt;( &lt;span style="color: magenta;"&gt;x &lt;/span&gt;=&amp;gt; &lt;span style="color: magenta;"&gt;1&lt;/span&gt;, &lt;span style="color: magenta;"&gt;y &lt;/span&gt;=&amp;gt; &lt;span style="color: magenta;"&gt;1&lt;/span&gt;, &lt;span style="color: magenta;"&gt;z &lt;/span&gt;=&amp;gt; &lt;span style="color: magenta;"&gt;1&lt;/span&gt; );&lt;br /&gt;&lt;span style="color: brown;"&gt;6 &lt;/span&gt;&lt;br /&gt;&lt;span style="color: brown;"&gt;7 &lt;/span&gt;say &lt;span style="color: magenta;"&gt;"&lt;/span&gt;&lt;span style="color: magenta;"&gt;Distance: &lt;/span&gt;&lt;span style="color: magenta;"&gt;"&lt;/span&gt;, &lt;span style="color: darkcyan;"&gt;$p1&lt;/span&gt;&lt;span style="color: darkcyan;"&gt;-&amp;gt;distance&lt;/span&gt;(&lt;span style="color: darkcyan;"&gt;$p2&lt;/span&gt;);&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;Notese que la invocación &lt;code&gt;&lt;span style="color: darkcyan;"&gt;$p1&lt;/span&gt;&lt;span style="color: darkcyan;"&gt;-&amp;gt;distance&lt;/span&gt;(&lt;span style="color: darkcyan;"&gt;$p2&lt;/span&gt;)&lt;/code&gt; invoca el método &lt;code&gt;&lt;span style="color: darkcyan;"&gt;distance&lt;/span&gt;&lt;/code&gt; heredado de Point, que a su vez utiliza la envoltura &lt;code&gt;&lt;span style="color: magenta;"&gt;distance_sqr&lt;/span&gt;&lt;/code&gt; de Point3D, que internamente invoca al método  &lt;code&gt;&lt;span style="color: darkcyan;"&gt;distance_sqr&lt;/span&gt;&lt;/code&gt; de Point.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5238463735728501931-5806421058337246937?l=perliscopio.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://perliscopio.blogspot.com/feeds/5806421058337246937/comments/default' title='Enviar comentarios'/><link rel='replies' type='text/html' href='http://perliscopio.blogspot.com/2009/12/conociendo-moose.html#comment-form' title='3 comentarios'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5238463735728501931/posts/default/5806421058337246937'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5238463735728501931/posts/default/5806421058337246937'/><link rel='alternate' type='text/html' href='http://perliscopio.blogspot.com/2009/12/conociendo-moose.html' title='Conociendo al alce (Moose)'/><author><name>Jose Rey</name><uri>http://www.blogger.com/profile/15071755167581242815</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>3</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5238463735728501931.post-4915817614399902638</id><published>2009-12-07T08:36:00.002-04:30</published><updated>2009-12-07T08:40:29.080-04:30</updated><category scheme='http://www.blogger.com/atom/ns#' term='Perl'/><category scheme='http://www.blogger.com/atom/ns#' term='CPAN'/><title type='text'>Rendimiento en PSGI/Plack</title><content type='html'>[&lt;a href="http://perliscope.blogspot.com/2009/12/plackpsgi-performance.html"&gt;English translation&lt;/a&gt;]&lt;br /&gt;En mi articulo sobre PSGI aseveré que Plack era rápido, para demostrarlo comparé la velocidad del programa ejecutándose como CGI en apache (ACGI), como un servidor standalone en CGI::Emulate::PSGI (CEP) y como una aplicación nativa de PSGI.&lt;br /&gt;&lt;br /&gt;La prueba no fue muy rigurosa, porque en realidad solo quería confirmar lo que había leído.&lt;br /&gt;&lt;br /&gt;El comando para reportar la velocidad fue:&lt;br /&gt;&lt;br /&gt;&lt;code&gt;$ ab -n 1000 -c 10 -k "http://localhost:5000/cgi-bin/perldocweb?pod=PSGI&amp;amp;format=source"&lt;/code&gt;&lt;br /&gt;&lt;br /&gt;Los resultados obtenidos fueron:&lt;br /&gt;&lt;br /&gt;&lt;table&gt;&lt;tbody&gt;&lt;tr style="text-align: center;"&gt; &lt;th&gt;&lt;/th&gt; &lt;th&gt;ACGI&lt;br /&gt;&lt;/th&gt; &lt;th&gt;CEP&lt;br /&gt;&lt;/th&gt; &lt;th&gt;PSGI&lt;br /&gt;&lt;/th&gt; &lt;/tr&gt;&lt;tr&gt; &lt;td&gt;Peticiones/seg.&lt;br /&gt;&lt;/td&gt; &lt;td style="text-align: right;"&gt;10.57&lt;br /&gt;&lt;/td&gt; &lt;td style="text-align: right;"&gt;267.17&lt;br /&gt;&lt;/td&gt; &lt;td style="text-align: right;"&gt;512.31&lt;br /&gt;&lt;/td&gt; &lt;/tr&gt;&lt;tr&gt; &lt;td&gt;Tiempo de ejecución (ms)&lt;br /&gt;&lt;/td&gt; &lt;td style="text-align: right;"&gt;94.618&lt;br /&gt;&lt;/td&gt; &lt;td style="text-align: right;"&gt;3.743&lt;br /&gt;&lt;/td&gt; &lt;td style="text-align: right;"&gt;1.952&lt;br /&gt;&lt;/td&gt; &lt;/tr&gt;&lt;tr&gt; &lt;td&gt;Rata de transf. (kBps)&lt;br /&gt;&lt;/td&gt; &lt;td style="text-align: right;"&gt;179.52&lt;br /&gt;&lt;/td&gt; &lt;td style="text-align: right;"&gt;4539.79&lt;br /&gt;&lt;/td&gt; &lt;td style="text-align: right;"&gt;8686.67&lt;br /&gt;&lt;/td&gt; &lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;br /&gt;Solo por ver la velocidad cruda, me hice un pequeño programa para servir archivos de texto y comparar el rendimiento contra apache sirviendo archivos estáticos:&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;span style="color: brown;"&gt; 1 &lt;/span&gt;&lt;span style="color: #a020f0;"&gt;#!&lt;/span&gt;&lt;span style="color: #a020f0;"&gt;/usr/bin/perl&lt;/span&gt;&lt;br /&gt;&lt;span style="color: brown;"&gt; 2 &lt;/span&gt;&lt;br /&gt;&lt;span style="color: brown;"&gt; 3 &lt;/span&gt;&lt;span style="color: #a020f0;"&gt;use &lt;/span&gt;Modern::Perl;&lt;br /&gt;&lt;span style="color: brown;"&gt; 4 &lt;/span&gt;&lt;span style="color: #a020f0;"&gt;use &lt;/span&gt;IO::File;&lt;br /&gt;&lt;span style="color: brown;"&gt; 5 &lt;/span&gt;&lt;br /&gt;&lt;span style="color: brown;"&gt; 6 &lt;/span&gt;&lt;span style="color: brown;"&gt;&lt;b&gt;my&lt;/b&gt;&lt;/span&gt; &lt;span style="color: darkcyan;"&gt;$dir&lt;/span&gt; = &lt;span style="color: magenta;"&gt;"&lt;/span&gt;&lt;span style="color: magenta;"&gt;/home/jrey/htdocs&lt;/span&gt;&lt;span style="color: magenta;"&gt;"&lt;/span&gt;;&lt;br /&gt;&lt;span style="color: brown;"&gt; 7 &lt;/span&gt;&lt;br /&gt;&lt;span style="color: brown;"&gt; 8 &lt;/span&gt;&lt;span style="color: brown;"&gt;&lt;b&gt;my&lt;/b&gt;&lt;/span&gt; &lt;span style="color: darkcyan;"&gt;$app&lt;/span&gt; =&lt;span style="color: darkcyan;"&gt; &lt;/span&gt;&lt;span style="color: brown;"&gt;&lt;b&gt;sub&lt;/b&gt;&lt;/span&gt;&lt;span style="color: darkcyan;"&gt; &lt;/span&gt;{&lt;br /&gt;&lt;span style="color: brown;"&gt; 9 &lt;/span&gt;    &lt;span style="color: brown;"&gt;&lt;b&gt;my&lt;/b&gt;&lt;/span&gt; &lt;span style="color: darkcyan;"&gt;$env&lt;/span&gt;      = &lt;span style="color: brown;"&gt;&lt;b&gt;shift&lt;/b&gt;&lt;/span&gt;;&lt;br /&gt;&lt;span style="color: brown;"&gt;10 &lt;/span&gt;    &lt;span style="color: brown;"&gt;&lt;b&gt;my&lt;/b&gt;&lt;/span&gt; &lt;span style="color: darkcyan;"&gt;$filename&lt;/span&gt; = &lt;span style="color: darkcyan;"&gt;$dir&lt;/span&gt; . &lt;span style="color: darkcyan;"&gt;$env-&amp;gt;{&lt;/span&gt;&lt;span style="color: magenta;"&gt;'&lt;/span&gt;&lt;span style="color: magenta;"&gt;REQUEST_URI&lt;/span&gt;&lt;span style="color: magenta;"&gt;'&lt;/span&gt;&lt;span style="color: darkcyan;"&gt;}&lt;/span&gt;;&lt;br /&gt;&lt;span style="color: brown;"&gt;11 &lt;/span&gt;    &lt;span style="color: brown;"&gt;&lt;b&gt;return&lt;/b&gt;&lt;/span&gt; [ &lt;span style="color: magenta;"&gt;'&lt;/span&gt;&lt;span style="color: magenta;"&gt;200&lt;/span&gt;&lt;span style="color: magenta;"&gt;'&lt;/span&gt;, [&lt;span style="color: magenta;"&gt;'&lt;/span&gt;&lt;span style="color: magenta;"&gt;Content-Type&lt;/span&gt;&lt;span style="color: magenta;"&gt;'&lt;/span&gt; =&amp;gt; &lt;span style="color: magenta;"&gt;"&lt;/span&gt;&lt;span style="color: magenta;"&gt;text/plain&lt;/span&gt;&lt;span style="color: magenta;"&gt;"&lt;/span&gt;], IO::File-&amp;gt;&lt;span style="color: brown;"&gt;&lt;b&gt;new&lt;/b&gt;&lt;/span&gt;(&lt;span style="color: darkcyan;"&gt;$filename&lt;/span&gt;) ];&lt;br /&gt;&lt;span style="color: brown;"&gt;12 &lt;/span&gt;};&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;Los resultados para el comando:&lt;br /&gt;&lt;br /&gt;&lt;code&gt;$ ab -n 1000 -c 10 -k "http://localhost:5000/PSGI.pod"&lt;/code&gt;&lt;br /&gt;&lt;br /&gt;Fueron:&lt;br /&gt;&lt;br /&gt;&lt;table&gt;&lt;tbody&gt;&lt;tr style="text-align: center;"&gt; &lt;th&gt;&lt;/th&gt; &lt;th&gt;Plackup&lt;br /&gt;&lt;/th&gt; &lt;th&gt;Apache&lt;br /&gt;&lt;/th&gt; &lt;/tr&gt;&lt;tr&gt; &lt;td&gt;Peticiones/seg.&lt;br /&gt;&lt;/td&gt; &lt;td style="text-align: right;"&gt;614.69&lt;br /&gt;&lt;/td&gt; &lt;td style="text-align: right;"&gt;3217.03&lt;br /&gt;&lt;/td&gt; &lt;/tr&gt;&lt;tr&gt; &lt;td&gt;Tiempo de ejecución (ms)&lt;br /&gt;&lt;/td&gt; &lt;td style="text-align: right;"&gt;1.627&lt;br /&gt;&lt;/td&gt; &lt;td style="text-align: right;"&gt;0.311&lt;br /&gt;&lt;/td&gt; &lt;/tr&gt;&lt;tr&gt; &lt;td&gt;Rata de transf. (kBps)&lt;br /&gt;&lt;/td&gt; &lt;td style="text-align: right;"&gt;10425.21&lt;br /&gt;&lt;/td&gt; &lt;td style="text-align: right;"&gt;55133.41&lt;br /&gt;&lt;/td&gt; &lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;br /&gt;Como dije antes, Plack es muy rápido, y en particular esta prueba muestra que el rendimiento es aceptable incluso para contenido estático, así que podremos desplegar las aplicaciones directamente en perl, sin necesidad de un servidor web adicional, excepto para circunstancias especiales, como alta disponibilidad y balanceo de carga, en cuyo caso también hay algunas soluciones en Perl como &lt;a href="http://www.danga.com/perlbal/"&gt;perlbal&lt;/a&gt;. ¿ya les mencioné existe &lt;a href="http://github.com/miyagawa/Perlbal-Plugin-PSGI"&gt;PSGI para perlbal&lt;/a&gt;?&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5238463735728501931-4915817614399902638?l=perliscopio.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://perliscopio.blogspot.com/feeds/4915817614399902638/comments/default' title='Enviar comentarios'/><link rel='replies' type='text/html' href='http://perliscopio.blogspot.com/2009/12/rendimiento-en-psgiplack.html#comment-form' title='0 comentarios'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5238463735728501931/posts/default/4915817614399902638'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5238463735728501931/posts/default/4915817614399902638'/><link rel='alternate' type='text/html' href='http://perliscopio.blogspot.com/2009/12/rendimiento-en-psgiplack.html' title='Rendimiento en PSGI/Plack'/><author><name>Jose Rey</name><uri>http://www.blogger.com/profile/15071755167581242815</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5238463735728501931.post-5928141905572359574</id><published>2009-12-06T19:26:00.002-04:30</published><updated>2009-12-06T22:16:34.583-04:30</updated><category scheme='http://www.blogger.com/atom/ns#' term='Perl'/><category scheme='http://www.blogger.com/atom/ns#' term='CPAN'/><title type='text'>Error en CGI::Emulate::PSGI</title><content type='html'>Mientras trabajaba con el código del &lt;a href="http://perliscopio.blogspot.com/2009/11/psgi-y-plack-el-futuro-de-las.html"&gt;articulo anterior&lt;/a&gt;, me dí cuenta de que en realidad el ejemplo sobre &lt;code&gt;CGI::Emulate::PSGI&lt;/code&gt; no funcionaba correctamente, debido a que no reinicié las variables globales de &lt;code&gt;CGI&lt;/code&gt;.&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;span style="color: brown;"&gt;1 &lt;/span&gt;&lt;span style="color: #a020f0;"&gt;use &lt;/span&gt;CGI::Emulate::PSGI;&lt;br /&gt;&lt;span style="color: brown;"&gt;2 &lt;/span&gt;&lt;span style="color: #a020f0;"&gt;use &lt;/span&gt;CGI;&lt;br /&gt;&lt;span style="color: brown;"&gt;3 &lt;/span&gt;&lt;br /&gt;&lt;span style="color: brown;"&gt;4 &lt;/span&gt;&lt;span style="color: brown;"&gt;&lt;b&gt;my&lt;/b&gt;&lt;/span&gt; &lt;span style="color: darkcyan;"&gt;$app&lt;/span&gt; = CGI::Emulate::PSGI-&amp;gt;handler(&lt;span style="color: brown;"&gt;&lt;b&gt;sub&lt;/b&gt;&lt;/span&gt;&lt;span style="color: darkcyan;"&gt; &lt;/span&gt;{&lt;br /&gt;&lt;span style="color: brown;"&gt;5 &lt;/span&gt;    CGI::initialize_globals();&lt;br /&gt;&lt;span style="color: brown;"&gt;6 &lt;/span&gt;    &lt;span style="color: brown;"&gt;&lt;b&gt;do&lt;/b&gt;&lt;/span&gt; &lt;span style="color: magenta;"&gt;"&lt;/span&gt;&lt;span style="color: magenta;"&gt;perldocweb&lt;/span&gt;&lt;span style="color: magenta;"&gt;"&lt;/span&gt;;&lt;br /&gt;&lt;span style="color: brown;"&gt;7 &lt;/span&gt;})&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;De otro modo los parámetros del primer request se quedan fijos para siempre.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5238463735728501931-5928141905572359574?l=perliscopio.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://perliscopio.blogspot.com/feeds/5928141905572359574/comments/default' title='Enviar comentarios'/><link rel='replies' type='text/html' href='http://perliscopio.blogspot.com/2009/12/error-en-cgiemulatepsgi.html#comment-form' title='0 comentarios'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5238463735728501931/posts/default/5928141905572359574'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5238463735728501931/posts/default/5928141905572359574'/><link rel='alternate' type='text/html' href='http://perliscopio.blogspot.com/2009/12/error-en-cgiemulatepsgi.html' title='Error en CGI::Emulate::PSGI'/><author><name>Jose Rey</name><uri>http://www.blogger.com/profile/15071755167581242815</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5238463735728501931.post-3819201169182018903</id><published>2009-11-30T01:19:00.006-04:30</published><updated>2009-11-30T10:47:21.904-04:30</updated><category scheme='http://www.blogger.com/atom/ns#' term='Web'/><category scheme='http://www.blogger.com/atom/ns#' term='Tutorial'/><category scheme='http://www.blogger.com/atom/ns#' term='Perl'/><category scheme='http://www.blogger.com/atom/ns#' term='CPAN'/><title type='text'>PSGI y Plack: el futuro de las aplicaciones web</title><content type='html'>[&lt;a href="http://perliscope.blogspot.com/2009/11/psgi-and-plack-future-of-web.html"&gt;English translation&lt;/a&gt;]&lt;br /&gt;Hace unas semanas le mostraba a mi amigo Joel un one-liner de Perl que implementaba un servidor web, tal vez tenía mucho trabajo que hacer porque no pareció sorprendido por esta fantástica línea de perl que usa el módulo IO::All:&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;perl -MIO::All -e 'io(&lt;span style="color: magenta;"&gt;"&lt;/span&gt;&lt;span style="color: magenta;"&gt;:8080&lt;/span&gt;&lt;span style="color: magenta;"&gt;"&lt;/span&gt;)-&amp;gt;&lt;span style="color: brown;"&gt;&lt;b&gt;fork&lt;/b&gt;&lt;/span&gt;-&amp;gt;&lt;span style="color: brown;"&gt;&lt;b&gt;accept&lt;/b&gt;&lt;/span&gt;-&amp;gt;(&lt;span style="color: brown;"&gt;&lt;b&gt;sub&lt;/b&gt;&lt;/span&gt;&lt;span style="color: darkcyan;"&gt; &lt;/span&gt;{ &lt;span style="color: darkcyan;"&gt;$_[&lt;/span&gt;&lt;span style="color: magenta;"&gt;0&lt;/span&gt;&lt;span style="color: darkcyan;"&gt;]&lt;/span&gt; &amp;lt; io(&lt;span style="color: brown;"&gt;&lt;b&gt;-x&lt;/b&gt;&lt;/span&gt; &lt;span style="color: darkcyan;"&gt;$1&lt;/span&gt; ? &lt;span style="color: magenta;"&gt;"&lt;/span&gt;&lt;span style="color: magenta;"&gt;./&lt;/span&gt;&lt;span style="color: darkcyan;"&gt;$1&lt;/span&gt;&lt;span style="color: magenta;"&gt; |&lt;/span&gt;&lt;span style="color: magenta;"&gt;"&lt;/span&gt; : &lt;span style="color: darkcyan;"&gt;$1&lt;/span&gt;) &lt;span style="color: brown;"&gt;&lt;b&gt;if&lt;/b&gt;&lt;/span&gt;&lt;span style="color: brown;"&gt;&lt;b&gt; /&lt;/b&gt;&lt;/span&gt;&lt;span style="color: magenta;"&gt;^GET &lt;/span&gt;&lt;span style="color: slateblue;"&gt;\/&lt;/span&gt;&lt;span style="color: slateblue;"&gt;(.*)&lt;/span&gt;&lt;span style="color: magenta;"&gt; &lt;/span&gt;&lt;span style="color: brown;"&gt;&lt;b&gt;/&lt;/b&gt;&lt;/span&gt; })'&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;Pero además sorprendentemente (sobre todo para un fanático de Perl) su respuesta fue: "Sabes que la gente de Python tiene software para implementar servidores web con muchísima facilidad, aunque no se cuál es", ahí me dí cuenta de que no entendió el punto, tal vez lo agarre en un mal momento así que lo deje ir.&lt;br /&gt;&lt;br /&gt;Pero ya me había intrigado, aunque estaba seguro que se refería a &lt;a href="http://wsgi.org/wsgi/"&gt;WSGI&lt;/a&gt; (también conocido como el &lt;a href="http://www.python.org/dev/peps/pep-0333/"&gt;PEP-333&lt;/a&gt;): una especificación para un API de aplicaciones web, permitiendo la separación e responsabilidades entre la interfaz (política) y su implementación (mecanismos), de manera que los desarrolladores se pueden preocupar por desarrollar y optimizar los mecanismos independientemente de las aplicaciones que los utilizan.&lt;br /&gt;&lt;br /&gt;En Perl ese era el trabajo de &lt;a href="http://search.cpan.org/perldoc?HTTP::Engine"&gt;HTTP::Engine&lt;/a&gt; utilizado entre otros por &lt;a href="http://www.catalystframework.org/"&gt;Catalyst&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;Sin embargo, me quedó la curiosidad y me puse a buscar en CPAN, ¿habría algo nuevo por allí?. Encontré módulos como &lt;a href="http://mojolicious.org/"&gt;Mojo&lt;/a&gt;, que utilizan internamente una interfaz similar a WSGI, sin embargo lo más interesante que conseguí fue &lt;a href="http://plackperl.org/"&gt;PSGI y Plack&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;Al parecer &lt;a href="http://search.cpan.org/perldoc?HTTP::Engine"&gt;HTTP::Engine&lt;/a&gt; está lejos de ser una solución ideal. Según he leído es monolítico, difícil de adaptar y no muy eficiente, para ambientes integrados (embedded) supongo. Lo cierto es que &lt;a href="http://profile.typepad.com/miyagawa"&gt;Miyagawa&lt;/a&gt; decidió separar  &lt;a href="http://search.cpan.org/perldoc?HTTP::Engine"&gt;HTTP::Engine&lt;/a&gt; en tres partes:&lt;br /&gt;&lt;ol&gt;&lt;li&gt;La Especificación: &lt;a href="http://search.cpan.org/perldoc?PSGI"&gt;PSGI&lt;/a&gt;&lt;/li&gt;&lt;li&gt;Una implementación de referencia: &lt;a href="http://search.cpan.org/perldoc?Plack::Server"&gt;Plack::Server&lt;/a&gt;&lt;/li&gt;&lt;li&gt;Herramientas: &lt;a href="http://search.cpan.org/perldoc?Plack"&gt;Plack::*&lt;/a&gt;&lt;/li&gt;&lt;/ol&gt;&lt;br /&gt;Lo más interesante de &lt;a href="http://plackperl.org/"&gt;PSGI y Plack&lt;/a&gt; es la rapidez con la que se implementó, hace solo semanas era una idea y ya están disponibles desde hace algún tiempo implementaciones de referencia que permiten ejecutar aplicaciones Plack por si mismas (standalone) en un solo hilo o con perfork, también hay interfaces para FastCGI, CGI y por supuesto mod-perl, y como si esto fuera poco, PSGI tiene la capacidad trabajar con sin bloqueo de entrada/salida (non blocking I/O), así que se hicieron servidores basados en &lt;a href="http://search.cpan.org/perldoc?POE"&gt;POE&lt;/a&gt;, &lt;a href="http://search.cpan.org/perldoc?AnyEvent"&gt;AnyEvent&lt;/a&gt; y &lt;a href="http://search.cpan.org/perldoc?Coro"&gt;Coro&lt;/a&gt;, incluso ya está disponible un módulo de PSGI para Apache (&lt;a href="http://github.com/spiritloose/mod_psgi/"&gt;mod-psgi&lt;/a&gt;).&lt;br /&gt;&lt;br /&gt;Por otra parte, de la nada aparecieron adaptadores de PSGI para frameworks como &lt;a href="http://www.catalystframework.org/"&gt;Catalyst&lt;/a&gt; (&lt;a href="http://search.cpan.org/perldoc?Catalyst::Engine::PSGI"&gt;Catalyst::Engine::PSGI&lt;/a&gt;), &lt;a href="http://search.cpan.org/perldoc?Squatting"&gt;Squatting&lt;/a&gt; (&lt;a href="http://search.cpan.org/perldoc?Squatting::On::PSGI"&gt;Squatting::On::PSGI&lt;/a&gt;), &lt;a href="http://search.cpan.org/perldoc?CGI::Application"&gt;CGI::Application&lt;/a&gt; (&lt;a href="http://search.cpan.org/perldoc?CGI::Application::PSGI"&gt;CGI::Application::PSGI&lt;/a&gt;), &lt;a href="http://dancer.sukria.net/"&gt;Dancer&lt;/a&gt; y hasta para &lt;a href="http://www.webgui.org/"&gt;WebGUI&lt;/a&gt; (&lt;a href="http://blog.patspam.com/2009/plebgui-webgui-meets-plack"&gt;PlebGUI&lt;/a&gt;), también hay herramientas para facilitar la migración de otras tecnologías a PSGI, por ejemplo si tienes alguna aplicación escrita para &lt;a href="http://search.cpan.org/perldoc?HTTP::Engine"&gt;HTTP::Engine&lt;/a&gt;, puedes utilizarla prácticamente sin modificación en PSGI con &lt;a href="http://search.cpan.org/perldoc?HTTP::Engine::Interface::PSGI"&gt;HTTP::Engine::Interface::PSGI&lt;/a&gt; , si tienes alguna aplicación CGI tienes la oportunidad de migrarla con muy pocas modificaciones con &lt;a href="http://search.cpan.org/perldoc?CGI::PSGI"&gt;CGI::PSGI&lt;/a&gt;, y si aún esto es demasiado trabajo puedes usar &lt;a href="http://search.cpan.org/perldoc?CGI::Emulate::PSGI"&gt;CGI::Emulate::PSGI&lt;/a&gt; que permite ejecutar los CGI como un servidor desde la línea de comandos!.&lt;br /&gt;&lt;br /&gt;En el &lt;a href="http://perliscope.blogspot.com/2009/11/processing-pod-with-podsimple.html"&gt;articulo anterior&lt;/a&gt; hice un servidorcito de documentos POD que implementé como CGI, seguramente más de uno tuvo problemas para hacerlo funcionar, porque hay que montar el web server y configurar el CGI entre otros. Usando &lt;a href="http://search.cpan.org/perldoc?CGI::Emulate::PSGI"&gt;CGI::Emulate::PSGI&lt;/a&gt; solamente escribimos un programa que inicie el servidor (perldocweb_starter):&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;span style="color: brown;"&gt;1 &lt;/span&gt;&lt;span style="color: #a020f0;"&gt;use &lt;/span&gt;CGI::Emulate::PSGI;&lt;br /&gt;&lt;span style="color: brown;"&gt;2 &lt;/span&gt;&lt;span style="color: brown;"&gt;&lt;b&gt;my&lt;/b&gt;&lt;/span&gt; &lt;span style="color: darkcyan;"&gt;$app&lt;/span&gt; = CGI::Emulate::PSGI-&amp;gt;handler(&lt;span style="color: brown;"&gt;&lt;b&gt;sub&lt;/b&gt;&lt;/span&gt;&lt;span style="color: darkcyan;"&gt; &lt;/span&gt;{ &lt;span style="color: brown;"&gt;&lt;b&gt;do&lt;/b&gt;&lt;/span&gt; &lt;span style="color: magenta;"&gt;"&lt;/span&gt;&lt;span style="color: magenta;"&gt;perldocweb&lt;/span&gt;&lt;span style="color: magenta;"&gt;"&lt;/span&gt; })&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;y luego ejecutamos el comando plackup:&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;$ plackup perldocweb_starter&lt;br /&gt;Plack::Server::Standalone: Accepting connections at http://0:5000/&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;y ahora tenemos nuestro servidor de documentación ejecutándose en el puerto 5000, así que al visitar:&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;http://localhost:5000/perldocweb?PSGI&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;Debería aparecer la especificación de PSGI en el navegador, fácil ¿no?.&lt;br /&gt;&lt;br /&gt;Ahora si estamos dispuestos a tocar el código del programa, no necesitaremos el emulador y podremos ejecutar la aplicación directamente con &lt;a href="http://search.cpan.org/perldoc?plackup"&gt;plackup&lt;/a&gt;, lo cual es mucho más eficiente.&lt;br /&gt;&lt;br /&gt;La primera modificación es cambiar la línea 4 para usar &lt;a href="http://search.cpan.org/perldoc?CGI::PSGI"&gt;CGI::PSGI&lt;/a&gt;, además ya no se usa &lt;a href="http://search.cpan.org/perldoc?CGI::Carp"&gt;CGI::Carp&lt;/a&gt;, porque Plack tiene una manera mucho más elegante de mostrar los errores utilizando &lt;a href="http://search.cpan.org/perldoc?Devel::StackTrace::AsHTML"&gt;Devel::StackTrace::AsHTML&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;Cuando usamos CGI::PSGI el programa debe crear (y retornar) una clausura que será nuestra aplicación así que el código principal entre las líneas 20 y 50 debe encerrarse en una clausura,  además la línea 20 ahora debe inicializar un objeto CGI::PSGI, así que la reemplazamos por las líneas 20 a 22 de en la nueva aplicación:&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;span style="color: brown;"&gt; 1 &lt;/span&gt;&lt;span style="color: #a020f0;"&gt;#!&lt;/span&gt;&lt;span style="color: #a020f0;"&gt;/usr/bin/perl&lt;/span&gt;&lt;br /&gt;&lt;span style="color: brown;"&gt; 2 &lt;/span&gt;&lt;br /&gt;&lt;span style="color: brown;"&gt; 3 &lt;/span&gt;&lt;span style="color: #a020f0;"&gt;use &lt;/span&gt;Modern::Perl;&lt;br /&gt;&lt;span style="color: brown;"&gt; 4 &lt;/span&gt;&lt;span style="color: #a020f0;"&gt;use &lt;/span&gt;CGI::PSGI;&lt;br /&gt;&lt;span style="color: brown;"&gt; 5 &lt;/span&gt;&lt;span style="color: #a020f0;"&gt;use &lt;/span&gt;IO::File;&lt;br /&gt;&lt;span style="color: brown;"&gt; 6 &lt;/span&gt;&lt;span style="color: #a020f0;"&gt;use &lt;/span&gt;Pod::Simple::Search;&lt;br /&gt;&lt;span style="color: brown;"&gt; 7 &lt;/span&gt;&lt;span style="color: #a020f0;"&gt;use &lt;/span&gt;Pod::Simple::HTML;&lt;br /&gt;&lt;span style="color: brown;"&gt; 8 &lt;/span&gt;&lt;br /&gt;&lt;span style="color: brown;"&gt; 9 &lt;/span&gt;&lt;span style="color: brown;"&gt;&lt;b&gt;my&lt;/b&gt;&lt;/span&gt; &lt;span style="color: darkcyan;"&gt;%content_types&lt;/span&gt; = (&lt;br /&gt;&lt;span style="color: brown;"&gt;10 &lt;/span&gt;    &lt;span style="color: magenta;"&gt;RTF   &lt;/span&gt;=&amp;gt; &lt;span style="color: magenta;"&gt;"&lt;/span&gt;&lt;span style="color: magenta;"&gt;application/rtf&lt;/span&gt;&lt;span style="color: magenta;"&gt;"&lt;/span&gt;,&lt;br /&gt;&lt;span style="color: brown;"&gt;11 &lt;/span&gt;    &lt;span style="color: magenta;"&gt;LaTeX &lt;/span&gt;=&amp;gt; &lt;span style="color: magenta;"&gt;"&lt;/span&gt;&lt;span style="color: magenta;"&gt;application/x-latex&lt;/span&gt;&lt;span style="color: magenta;"&gt;"&lt;/span&gt;,&lt;br /&gt;&lt;span style="color: brown;"&gt;12 &lt;/span&gt;    &lt;span style="color: magenta;"&gt;PDF   &lt;/span&gt;=&amp;gt; &lt;span style="color: magenta;"&gt;"&lt;/span&gt;&lt;span style="color: magenta;"&gt;application/pdf&lt;/span&gt;&lt;span style="color: magenta;"&gt;"&lt;/span&gt;,&lt;br /&gt;&lt;span style="color: brown;"&gt;13 &lt;/span&gt;);&lt;br /&gt;&lt;span style="color: brown;"&gt;14 &lt;/span&gt;&lt;span style="color: brown;"&gt;&lt;b&gt;my&lt;/b&gt;&lt;/span&gt; &lt;span style="color: darkcyan;"&gt;@wikis&lt;/span&gt;   = &lt;span style="color: magenta;"&gt;qw(&lt;/span&gt;&lt;span style="color: magenta;"&gt;Usemod Twiki Template Kwiki Confluence Moinmoin Tiddlywiki Mediawiki Textile&lt;/span&gt;&lt;span style="color: magenta;"&gt;)&lt;/span&gt;;&lt;br /&gt;&lt;span style="color: brown;"&gt;15 &lt;/span&gt;&lt;span style="color: brown;"&gt;&lt;b&gt;my&lt;/b&gt;&lt;/span&gt; &lt;span style="color: darkcyan;"&gt;%formats&lt;/span&gt; = (&lt;br /&gt;&lt;span style="color: brown;"&gt;16 &lt;/span&gt;    ( &lt;span style="color: brown;"&gt;&lt;b&gt;map&lt;/b&gt;&lt;/span&gt; { &lt;span style="color: darkcyan;"&gt;$_&lt;/span&gt; =&amp;gt; &lt;span style="color: magenta;"&gt;"&lt;/span&gt;&lt;span style="color: magenta;"&gt;Pod::Simple::&lt;/span&gt;&lt;span style="color: darkcyan;"&gt;$_&lt;/span&gt;&lt;span style="color: magenta;"&gt;"&lt;/span&gt; } &lt;span style="color: brown;"&gt;&lt;b&gt;keys&lt;/b&gt;&lt;/span&gt; &lt;span style="color: darkcyan;"&gt;%content_types&lt;/span&gt; ),&lt;br /&gt;&lt;span style="color: brown;"&gt;17 &lt;/span&gt;    ( &lt;span style="color: brown;"&gt;&lt;b&gt;map&lt;/b&gt;&lt;/span&gt; { &lt;span style="color: darkcyan;"&gt;$_&lt;/span&gt; =&amp;gt; &lt;span style="color: magenta;"&gt;"&lt;/span&gt;&lt;span style="color: magenta;"&gt;Pod::Simple::Wiki::&lt;/span&gt;&lt;span style="color: darkcyan;"&gt;$_&lt;/span&gt;&lt;span style="color: magenta;"&gt;"&lt;/span&gt; } &lt;span style="color: darkcyan;"&gt;@wikis&lt;/span&gt; )&lt;br /&gt;&lt;span style="color: brown;"&gt;18 &lt;/span&gt;);&lt;br /&gt;&lt;span style="color: brown;"&gt;19 &lt;/span&gt;&lt;br /&gt;&lt;span style="color: brown;"&gt;20 &lt;/span&gt;&lt;span style="color: brown;"&gt;&lt;b&gt;my&lt;/b&gt;&lt;/span&gt; &lt;span style="color: darkcyan;"&gt;$app&lt;/span&gt; =&lt;span style="color: darkcyan;"&gt; &lt;/span&gt;&lt;span style="color: brown;"&gt;&lt;b&gt;sub&lt;/b&gt;&lt;/span&gt;&lt;span style="color: darkcyan;"&gt; &lt;/span&gt;{&lt;br /&gt;&lt;span style="color: brown;"&gt;21 &lt;/span&gt;    &lt;span style="color: brown;"&gt;&lt;b&gt;my&lt;/b&gt;&lt;/span&gt; &lt;span style="color: darkcyan;"&gt;$env&lt;/span&gt;      = &lt;span style="color: brown;"&gt;&lt;b&gt;shift&lt;/b&gt;&lt;/span&gt;;&lt;br /&gt;&lt;span style="color: brown;"&gt;22 &lt;/span&gt;    &lt;span style="color: brown;"&gt;&lt;b&gt;my&lt;/b&gt;&lt;/span&gt; &lt;span style="color: darkcyan;"&gt;$q&lt;/span&gt;        = CGI::PSGI-&amp;gt;&lt;span style="color: brown;"&gt;&lt;b&gt;new&lt;/b&gt;&lt;/span&gt;(&lt;span style="color: darkcyan;"&gt;$env&lt;/span&gt;);&lt;br /&gt;&lt;span style="color: brown;"&gt;23 &lt;/span&gt;    &lt;span style="color: brown;"&gt;&lt;b&gt;my&lt;/b&gt;&lt;/span&gt; &lt;span style="color: darkcyan;"&gt;$filename&lt;/span&gt; = Pod::Simple::Search-&amp;gt;&lt;span style="color: brown;"&gt;&lt;b&gt;new&lt;/b&gt;&lt;/span&gt;-&amp;gt;inc(&lt;span style="color: magenta;"&gt;1&lt;/span&gt;)-&amp;gt;find( &lt;span style="color: darkcyan;"&gt;$q&lt;/span&gt;&lt;span style="color: darkcyan;"&gt;-&amp;gt;param&lt;/span&gt;(&lt;span style="color: magenta;"&gt;"&lt;/span&gt;&lt;span style="color: magenta;"&gt;pod&lt;/span&gt;&lt;span style="color: magenta;"&gt;"&lt;/span&gt;) );&lt;br /&gt;&lt;span style="color: brown;"&gt;24 &lt;/span&gt;    &lt;span style="color: brown;"&gt;&lt;b&gt;my&lt;/b&gt;&lt;/span&gt; &lt;span style="color: darkcyan;"&gt;$format&lt;/span&gt;   = &lt;span style="color: darkcyan;"&gt;$q&lt;/span&gt;&lt;span style="color: darkcyan;"&gt;-&amp;gt;param&lt;/span&gt;(&lt;span style="color: magenta;"&gt;"&lt;/span&gt;&lt;span style="color: magenta;"&gt;format&lt;/span&gt;&lt;span style="color: magenta;"&gt;"&lt;/span&gt;) || &lt;span style="color: magenta;"&gt;"&lt;/span&gt;&lt;span style="color: magenta;"&gt;HTML&lt;/span&gt;&lt;span style="color: magenta;"&gt;"&lt;/span&gt;;&lt;br /&gt;&lt;span style="color: brown;"&gt;25 &lt;/span&gt;    given (&lt;span style="color: darkcyan;"&gt;$format&lt;/span&gt;) {&lt;br /&gt;&lt;span style="color: brown;"&gt;26 &lt;/span&gt;        when (&lt;span style="color: magenta;"&gt;"&lt;/span&gt;&lt;span style="color: magenta;"&gt;source&lt;/span&gt;&lt;span style="color: magenta;"&gt;"&lt;/span&gt;) {&lt;br /&gt;&lt;span style="color: brown;"&gt;27 &lt;/span&gt;            &lt;span style="color: brown;"&gt;&lt;b&gt;return&lt;/b&gt;&lt;/span&gt; [ &lt;span style="color: darkcyan;"&gt;$q&lt;/span&gt;&lt;span style="color: darkcyan;"&gt;-&amp;gt;psgi_header&lt;/span&gt;(&lt;span style="color: magenta;"&gt;"&lt;/span&gt;&lt;span style="color: magenta;"&gt;text/plain&lt;/span&gt;&lt;span style="color: magenta;"&gt;"&lt;/span&gt;), IO::File-&amp;gt;&lt;span style="color: brown;"&gt;&lt;b&gt;new&lt;/b&gt;&lt;/span&gt;(&lt;span style="color: darkcyan;"&gt;$filename&lt;/span&gt;) ];&lt;br /&gt;&lt;span style="color: brown;"&gt;28 &lt;/span&gt;        }&lt;br /&gt;&lt;span style="color: brown;"&gt;29 &lt;/span&gt;        when (&lt;span style="color: magenta;"&gt;'&lt;/span&gt;&lt;span style="color: magenta;"&gt;HTML&lt;/span&gt;&lt;span style="color: magenta;"&gt;'&lt;/span&gt;) {&lt;br /&gt;&lt;span style="color: brown;"&gt;30 &lt;/span&gt;            &lt;span style="color: brown;"&gt;&lt;b&gt;my&lt;/b&gt;&lt;/span&gt; &lt;span style="color: darkcyan;"&gt;$parser&lt;/span&gt; = Pod::Simple::HTML-&amp;gt;&lt;span style="color: brown;"&gt;&lt;b&gt;new&lt;/b&gt;&lt;/span&gt;;&lt;br /&gt;&lt;span style="color: brown;"&gt;31 &lt;/span&gt;            &lt;span style="color: darkcyan;"&gt;$parser&lt;/span&gt;&lt;span style="color: darkcyan;"&gt;-&amp;gt;perldoc_url_prefix&lt;/span&gt;( &lt;span style="color: darkcyan;"&gt;$q&lt;/span&gt;&lt;span style="color: darkcyan;"&gt;-&amp;gt;url&lt;/span&gt;( -&lt;span style="color: magenta;"&gt;path_info &lt;/span&gt;=&amp;gt; &lt;span style="color: magenta;"&gt;1&lt;/span&gt; ) . &lt;span style="color: magenta;"&gt;"&lt;/span&gt;&lt;span style="color: magenta;"&gt;?pod=&lt;/span&gt;&lt;span style="color: magenta;"&gt;"&lt;/span&gt; );&lt;br /&gt;&lt;span style="color: brown;"&gt;32 &lt;/span&gt;            &lt;span style="color: brown;"&gt;&lt;b&gt;my&lt;/b&gt;&lt;/span&gt; &lt;span style="color: darkcyan;"&gt;$footer&lt;/span&gt; = &lt;span style="color: magenta;"&gt;"&lt;/span&gt;&lt;span style="color: magenta;"&gt;&amp;lt;hr&amp;gt;&lt;/span&gt;&lt;span style="color: magenta;"&gt;"&lt;/span&gt;&lt;br /&gt;&lt;span style="color: brown;"&gt;33 &lt;/span&gt;                . &lt;span style="color: brown;"&gt;&lt;b&gt;join&lt;/b&gt;&lt;/span&gt;( &lt;span style="color: magenta;"&gt;"&lt;/span&gt;&lt;span style="color: magenta;"&gt; &lt;/span&gt;&lt;span style="color: magenta;"&gt;"&lt;/span&gt;, &lt;span style="color: brown;"&gt;&lt;b&gt;map&lt;/b&gt;&lt;/span&gt; { make_link( &lt;span style="color: darkcyan;"&gt;$_&lt;/span&gt;, &lt;span style="color: darkcyan;"&gt;$q&lt;/span&gt; ) } &lt;span style="color: magenta;"&gt;"&lt;/span&gt;&lt;span style="color: magenta;"&gt;source&lt;/span&gt;&lt;span style="color: magenta;"&gt;"&lt;/span&gt;, &lt;span style="color: brown;"&gt;&lt;b&gt;keys&lt;/b&gt;&lt;/span&gt; &lt;span style="color: darkcyan;"&gt;%content_types&lt;/span&gt; )&lt;br /&gt;&lt;span style="color: brown;"&gt;34 &lt;/span&gt;                . &lt;span style="color: magenta;"&gt;"&lt;/span&gt;&lt;span style="color: magenta;"&gt; | Wiki formats: &lt;/span&gt;&lt;span style="color: magenta;"&gt;"&lt;/span&gt;&lt;br /&gt;&lt;span style="color: brown;"&gt;35 &lt;/span&gt;                . &lt;span style="color: brown;"&gt;&lt;b&gt;join&lt;/b&gt;&lt;/span&gt;( &lt;span style="color: magenta;"&gt;"&lt;/span&gt;&lt;span style="color: magenta;"&gt; &lt;/span&gt;&lt;span style="color: magenta;"&gt;"&lt;/span&gt;, &lt;span style="color: brown;"&gt;&lt;b&gt;map&lt;/b&gt;&lt;/span&gt; { make_link( &lt;span style="color: darkcyan;"&gt;$_&lt;/span&gt;, &lt;span style="color: darkcyan;"&gt;$q&lt;/span&gt; ) } &lt;span style="color: darkcyan;"&gt;@wikis&lt;/span&gt; );&lt;br /&gt;&lt;span style="color: brown;"&gt;36 &lt;/span&gt;            &lt;span style="color: darkcyan;"&gt;$parser&lt;/span&gt;&lt;span style="color: darkcyan;"&gt;-&amp;gt;html_footer&lt;/span&gt;(qq[\n&amp;lt;!-- end doc --&amp;gt;\n\n&lt;span style="color: darkcyan;"&gt;$footer&lt;/span&gt;&amp;lt;/body&amp;gt;&amp;lt;/html&amp;gt;\n]);&lt;br /&gt;&lt;span style="color: brown;"&gt;37 &lt;/span&gt;            &lt;span style="color: darkcyan;"&gt;$parser&lt;/span&gt;&lt;span style="color: darkcyan;"&gt;-&amp;gt;output_string&lt;/span&gt;( &lt;span style="color: brown;"&gt;&lt;b&gt;my&lt;/b&gt;&lt;/span&gt; &lt;span style="color: darkcyan;"&gt;$output&lt;/span&gt; );&lt;br /&gt;&lt;span style="color: brown;"&gt;38 &lt;/span&gt;            &lt;span style="color: darkcyan;"&gt;$parser&lt;/span&gt;&lt;span style="color: darkcyan;"&gt;-&amp;gt;parse_file&lt;/span&gt;(&lt;span style="color: darkcyan;"&gt;$filename&lt;/span&gt;);&lt;br /&gt;&lt;span style="color: brown;"&gt;39 &lt;/span&gt;            &lt;span style="color: brown;"&gt;&lt;b&gt;return&lt;/b&gt;&lt;/span&gt; [ &lt;span style="color: darkcyan;"&gt;$q&lt;/span&gt;&lt;span style="color: darkcyan;"&gt;-&amp;gt;psgi_header&lt;/span&gt;(&lt;span style="color: magenta;"&gt;"&lt;/span&gt;&lt;span style="color: magenta;"&gt;text/html&lt;/span&gt;&lt;span style="color: magenta;"&gt;"&lt;/span&gt;), [&lt;span style="color: darkcyan;"&gt;$output&lt;/span&gt;] ];&lt;br /&gt;&lt;span style="color: brown;"&gt;40 &lt;/span&gt;        }&lt;br /&gt;&lt;span style="color: brown;"&gt;41 &lt;/span&gt;        when (&lt;span style="color: darkcyan;"&gt;%formats&lt;/span&gt;) {&lt;br /&gt;&lt;span style="color: brown;"&gt;42 &lt;/span&gt;            &lt;span style="color: brown;"&gt;&lt;b&gt;my&lt;/b&gt;&lt;/span&gt; &lt;span style="color: darkcyan;"&gt;$class&lt;/span&gt; = &lt;span style="color: darkcyan;"&gt;$formats{$format}&lt;/span&gt;;&lt;br /&gt;&lt;span style="color: brown;"&gt;43 &lt;/span&gt;            &lt;span style="color: brown;"&gt;&lt;b&gt;eval&lt;/b&gt;&lt;/span&gt; &lt;span style="color: magenta;"&gt;"&lt;/span&gt;&lt;span style="color: magenta;"&gt;require &lt;/span&gt;&lt;span style="color: darkcyan;"&gt;$class&lt;/span&gt;&lt;span style="color: magenta;"&gt;"&lt;/span&gt;;&lt;br /&gt;&lt;span style="color: brown;"&gt;44 &lt;/span&gt;            &lt;span style="color: brown;"&gt;&lt;b&gt;my&lt;/b&gt;&lt;/span&gt; &lt;span style="color: darkcyan;"&gt;$parser&lt;/span&gt; = &lt;span style="color: darkcyan;"&gt;$class&lt;/span&gt;&lt;span style="color: darkcyan;"&gt;-&amp;gt;new&lt;/span&gt;;&lt;br /&gt;&lt;span style="color: brown;"&gt;45 &lt;/span&gt;            &lt;span style="color: darkcyan;"&gt;$parser&lt;/span&gt;&lt;span style="color: darkcyan;"&gt;-&amp;gt;output_string&lt;/span&gt;( &lt;span style="color: brown;"&gt;&lt;b&gt;my&lt;/b&gt;&lt;/span&gt; &lt;span style="color: darkcyan;"&gt;$output&lt;/span&gt; );&lt;br /&gt;&lt;span style="color: brown;"&gt;46 &lt;/span&gt;            &lt;span style="color: darkcyan;"&gt;$parser&lt;/span&gt;&lt;span style="color: darkcyan;"&gt;-&amp;gt;parse_file&lt;/span&gt;(&lt;span style="color: darkcyan;"&gt;$filename&lt;/span&gt;);&lt;br /&gt;&lt;span style="color: brown;"&gt;47 &lt;/span&gt;            &lt;span style="color: brown;"&gt;&lt;b&gt;return&lt;/b&gt;&lt;/span&gt; [ &lt;span style="color: darkcyan;"&gt;$q&lt;/span&gt;&lt;span style="color: darkcyan;"&gt;-&amp;gt;psgi_header&lt;/span&gt;( &lt;span style="color: darkcyan;"&gt;$content_types{$format}&lt;/span&gt; || &lt;span style="color: magenta;"&gt;"&lt;/span&gt;&lt;span style="color: magenta;"&gt;text/plain&lt;/span&gt;&lt;span style="color: magenta;"&gt;"&lt;/span&gt; ), [&lt;span style="color: darkcyan;"&gt;$output&lt;/span&gt;] ];&lt;br /&gt;&lt;span style="color: brown;"&gt;48 &lt;/span&gt;        }&lt;br /&gt;&lt;span style="color: brown;"&gt;49 &lt;/span&gt;        default {&lt;br /&gt;&lt;span style="color: brown;"&gt;50 &lt;/span&gt;            &lt;span style="color: brown;"&gt;&lt;b&gt;die&lt;/b&gt;&lt;/span&gt;(&lt;span style="color: magenta;"&gt;"&lt;/span&gt;&lt;span style="color: magenta;"&gt;Formato desconocido '&lt;/span&gt;&lt;span style="color: darkcyan;"&gt;$format&lt;/span&gt;&lt;span style="color: magenta;"&gt;'&lt;/span&gt;&lt;span style="color: magenta;"&gt;"&lt;/span&gt;);&lt;br /&gt;&lt;span style="color: brown;"&gt;51 &lt;/span&gt;        }&lt;br /&gt;&lt;span style="color: brown;"&gt;52 &lt;/span&gt;    }&lt;br /&gt;&lt;span style="color: brown;"&gt;53 &lt;/span&gt;};&lt;br /&gt;&lt;span style="color: brown;"&gt;54 &lt;/span&gt;&lt;br /&gt;&lt;span style="color: brown;"&gt;55 &lt;/span&gt;&lt;span style="color: brown;"&gt;&lt;b&gt;sub&lt;/b&gt;&lt;/span&gt;&lt;span style="color: darkcyan;"&gt; &lt;/span&gt;&lt;span style="color: darkcyan;"&gt;make_link &lt;/span&gt;{&lt;br /&gt;&lt;span style="color: brown;"&gt;56 &lt;/span&gt;    &lt;span style="color: brown;"&gt;&lt;b&gt;my&lt;/b&gt;&lt;/span&gt; &lt;span style="color: darkcyan;"&gt;$fmt&lt;/span&gt; = &lt;span style="color: brown;"&gt;&lt;b&gt;shift&lt;/b&gt;&lt;/span&gt;;&lt;br /&gt;&lt;span style="color: brown;"&gt;57 &lt;/span&gt;    &lt;span style="color: brown;"&gt;&lt;b&gt;my&lt;/b&gt;&lt;/span&gt; &lt;span style="color: darkcyan;"&gt;$q&lt;/span&gt;   = &lt;span style="color: brown;"&gt;&lt;b&gt;shift&lt;/b&gt;&lt;/span&gt;;&lt;br /&gt;&lt;span style="color: brown;"&gt;58 &lt;/span&gt;    &lt;span style="color: darkcyan;"&gt;$q&lt;/span&gt;&lt;span style="color: darkcyan;"&gt;-&amp;gt;a&lt;/span&gt;( { &lt;span style="color: magenta;"&gt;href &lt;/span&gt;=&amp;gt; &lt;span style="color: darkcyan;"&gt;$q&lt;/span&gt;&lt;span style="color: darkcyan;"&gt;-&amp;gt;url&lt;/span&gt;( -&lt;span style="color: magenta;"&gt;path_info &lt;/span&gt;=&amp;gt; &lt;span style="color: magenta;"&gt;1&lt;/span&gt;, -&lt;span style="color: magenta;"&gt;query &lt;/span&gt;=&amp;gt; &lt;span style="color: magenta;"&gt;1&lt;/span&gt; ) . &lt;span style="color: magenta;"&gt;"&lt;/span&gt;&lt;span style="color: slateblue;"&gt;\&amp;amp;&lt;/span&gt;&lt;span style="color: magenta;"&gt;format=&lt;/span&gt;&lt;span style="color: darkcyan;"&gt;$fmt&lt;/span&gt;&lt;span style="color: magenta;"&gt;"&lt;/span&gt; }, &lt;span style="color: darkcyan;"&gt;$fmt&lt;/span&gt; );&lt;br /&gt;&lt;span style="color: brown;"&gt;59 &lt;/span&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;La clausura recibe como parámetro el ambiente de PSGI (21) y lo utiliza para crear el objeto $q que usaremos como si fuera un objeto CGI. Esta clausura debe retornar un arreglo de dos elementos:&lt;br /&gt;&lt;ol&gt;&lt;li&gt;Los encabezados: un arreglo de nombres y valores alternados&lt;br /&gt;&lt;/li&gt;&lt;li&gt;El cuerpo: que debe ser un arreglo de líneas o un objeto &lt;a href="http://search.cpan.org/perldoc?IO::Handle"&gt;IO::Handle&lt;/a&gt;&lt;/li&gt;&lt;/ol&gt;&lt;br /&gt;Una diferencia fundamental entre &lt;a href="http://search.cpan.org/perldoc?CGI::PSGI"&gt;CGI::PSGI&lt;/a&gt; y &lt;a href="http://search.cpan.org/perldoc?CGI"&gt;CGI&lt;/a&gt; es que en el segundo se envía al navegador la salida estándar (STDOUT), mientras que en el primero, se retorna el cuerpo.&lt;br /&gt;&lt;br /&gt;Así que la generación del contenido en la aplicación debe ser modificada. En el caso del código fuente (línea 26) ha quedado más simple, solo se retornan los encabezados junto con un objeto &lt;a href="http://search.cpan.org/perldoc?IO::Handle"&gt;IO::Handle&lt;/a&gt; (creado con &lt;a href="http://search.cpan.org/perldoc?IO::File"&gt;IO::File&lt;/a&gt;). y CGI::PSGI se encarga de leer los datos del objeto y enviarlos al navegador, de hecho en el caso de que sea un archivo real (como en este caso) y que el sistema operativo implemente sendfile(2) (como en mi caso que uso linux), el envío de los datos se realiza completamente en el kernel así que no habrá diferencia de eficiencia entre este programa y uno optimizado hecho en C (como apache).&lt;br /&gt;&lt;br /&gt;En el caso de HTML (línea 29) he cambiado el uso de &lt;code&gt;output_fh&lt;/code&gt; por &lt;code&gt;output_string&lt;/code&gt; para que el contenido generado por &lt;a href="http://search.cpan.org/perldoc?Pod::Simple"&gt;Pod::Simple&lt;/a&gt; quede en $output, que se retorna en línea 39.&lt;br /&gt;&lt;br /&gt;Como ya no se puede usar el &lt;code&gt;STDOUT&lt;/code&gt; para enviar el contenido al navegador tampoco podemos utilizar el atajo &lt;code&gt;$class-&amp;gt;filter&lt;/code&gt; de &lt;a href="http://search.cpan.org/perldoc?Pod::Simple"&gt;Pod::Simple&lt;/a&gt;, así que lo he reemplazado por su equivalencia en las líneas 44 a 46 de la nueva aplicación.&lt;br /&gt;&lt;br /&gt;Aunque tal vez no es obvio, el código retorna la clausura (línea 20) porque es el último valor que se calcula, ya que lo que sigue es una declaración.&lt;br /&gt;&lt;br /&gt;Si llamamos a nuestro nuevo programa "server_pod" podremos arrancarlo con plackup de la siguiente manera:&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;$ plackup server_pod&lt;br /&gt;Plack::Server::Standalone: Accepting connections at http://0:5000/&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;y podemos visualizar el contenido de los POD utilizando el navegador como ya se indicó, el servidor que utiliza plackup por defecto (&lt;a href="http://search.cpan.org/perldoc?Plack::Server::Standalone"&gt;Plack::Server::Standalone&lt;/a&gt;) es de un proceso de un solo hilo así que es ideal para el desarrollo o para una aplicación personal, pero si necesitas un servidor con calidad de producción debes ver otras opciones, la más recomendable para código que viene de CGI es probablemente &lt;a href="http://search.cpan.org/perldoc?Plack::Server::Standalone::Prefork"&gt;Plack::Server::Standalone::Prefork&lt;/a&gt;, que puedes arrancar así:&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;$ plackup -s Standalone::Prefork server_pod&lt;br /&gt;Plack::Server::Standalone: Accepting connections at http://0:5000/&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;Eso fue fácil, se utilizan valores por defecto para todo, pero si necesitas entonar el rendimiento del servidor puedes hacerlo dado opciones en la línea de comandos, las opciones generales se documentan en &lt;a href="http://search.cpan.org/perldoc?plackup"&gt;plackup&lt;/a&gt; y las de cada servidor en su clase respectiva.&lt;br /&gt;&lt;br /&gt;Finalmente este código es mucho más eficiente que el del emulador del primer ejemplo porque no se necesita utilizar archivos temporales para capturar la salida estándar, aún así puede ejecutarse bajo Apache en modo CGI, FastCGI o incluso en mod-perl.&lt;br /&gt;&lt;br /&gt;En una próxima ocasión mejoraré la aplicación utilizando directamente Plack y su &lt;a href="http://search.cpan.org/perldoc?Plack::Middleware"&gt;middleware&lt;/a&gt;.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5238463735728501931-3819201169182018903?l=perliscopio.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://perliscopio.blogspot.com/feeds/3819201169182018903/comments/default' title='Enviar comentarios'/><link rel='replies' type='text/html' href='http://perliscopio.blogspot.com/2009/11/psgi-y-plack-el-futuro-de-las.html#comment-form' title='2 comentarios'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5238463735728501931/posts/default/3819201169182018903'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5238463735728501931/posts/default/3819201169182018903'/><link rel='alternate' type='text/html' href='http://perliscopio.blogspot.com/2009/11/psgi-y-plack-el-futuro-de-las.html' title='PSGI y Plack: el futuro de las aplicaciones web'/><author><name>Jose Rey</name><uri>http://www.blogger.com/profile/15071755167581242815</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5238463735728501931.post-2896200630160876143</id><published>2009-11-21T08:20:00.001-04:30</published><updated>2009-11-21T08:22:21.935-04:30</updated><category scheme='http://www.blogger.com/atom/ns#' term='Tutorial'/><category scheme='http://www.blogger.com/atom/ns#' term='Perl'/><category scheme='http://www.blogger.com/atom/ns#' term='CPAN'/><title type='text'>Procesando POD con Pod::Simple</title><content type='html'>[&lt;a href="http://perliscope.blogspot.com/2009/11/processing-pod-with-podsimple.html"&gt;English translation&lt;/a&gt;]&lt;br /&gt;En el &lt;a href="http://perliscopio.blogspot.com/2009/11/herramientas-de-documentacion-en-perl.html"&gt;artículo anterior&lt;/a&gt; logramos convertir POD a HTML con relativa facilidad para un minúsculo servidor de documentos hecho con CGI, hoy voy a expandir el programa, permitiendo la visualización de documentos POD en una docena de formas diferentes.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;Una opción útil cuando veo la documentación del CPAN, es la capacidad de mostrar las fuentes de los módulos, así que voy a agregar un enlace que permita visualizar la fuente de un documente, voy a poner el enlace al final del documento, configurando el footer de la conversión HTML, también debo agregar lógica para reconocer el nuevo tipo de enlaces.&lt;br /&gt;&lt;br /&gt;Agregaré un parámetro de formato (format) al query, y lo interpretaré con el given de la línea 12, además para ser compatible con la versión anterior, permitiré que el formato sea opcional, y su valor por omisión será HTML (línea 11):&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;span style="color: brown;"&gt; 1 &lt;/span&gt;&lt;span style="color: #a020f0;"&gt;#!&lt;/span&gt;&lt;span style="color: #a020f0;"&gt;/usr/bin/perl&lt;/span&gt;&lt;br /&gt;&lt;span style="color: brown;"&gt; 2 &lt;/span&gt;&lt;br /&gt;&lt;span style="color: brown;"&gt; 3 &lt;/span&gt;&lt;span style="color: #a020f0;"&gt;use &lt;/span&gt;Modern::Perl;&lt;br /&gt;&lt;span style="color: brown;"&gt; 4 &lt;/span&gt;&lt;span style="color: #a020f0;"&gt;use &lt;/span&gt;CGI;&lt;br /&gt;&lt;span style="color: brown;"&gt; 5 &lt;/span&gt;&lt;span style="color: #a020f0;"&gt;use &lt;/span&gt;CGI::Carp &lt;span style="color: magenta;"&gt;'&lt;/span&gt;&lt;span style="color: magenta;"&gt;fatalsToBrowser&lt;/span&gt;&lt;span style="color: magenta;"&gt;'&lt;/span&gt;;&lt;br /&gt;&lt;span style="color: brown;"&gt; 6 &lt;/span&gt;&lt;span style="color: #a020f0;"&gt;use &lt;/span&gt;Pod::Simple::Search;&lt;br /&gt;&lt;span style="color: brown;"&gt; 7 &lt;/span&gt;&lt;span style="color: #a020f0;"&gt;use &lt;/span&gt;Pod::Simple::HTML;&lt;br /&gt;&lt;span style="color: brown;"&gt; 8 &lt;/span&gt;&lt;br /&gt;&lt;span style="color: brown;"&gt; 9 &lt;/span&gt;&lt;span style="color: brown;"&gt;&lt;b&gt;my&lt;/b&gt;&lt;/span&gt; &lt;span style="color: darkcyan;"&gt;$q&lt;/span&gt;        = &lt;span style="color: brown;"&gt;&lt;b&gt;new&lt;/b&gt;&lt;/span&gt; CGI;&lt;br /&gt;&lt;span style="color: brown;"&gt;10 &lt;/span&gt;&lt;span style="color: brown;"&gt;&lt;b&gt;my&lt;/b&gt;&lt;/span&gt; &lt;span style="color: darkcyan;"&gt;$filename&lt;/span&gt; = Pod::Simple::Search-&amp;gt;&lt;span style="color: brown;"&gt;&lt;b&gt;new&lt;/b&gt;&lt;/span&gt;-&amp;gt;inc(&lt;span style="color: magenta;"&gt;1&lt;/span&gt;)-&amp;gt;find( &lt;span style="color: darkcyan;"&gt;$q&lt;/span&gt;&lt;span style="color: darkcyan;"&gt;-&amp;gt;param&lt;/span&gt;(&lt;span style="color: magenta;"&gt;"&lt;/span&gt;&lt;span style="color: magenta;"&gt;pod&lt;/span&gt;&lt;span style="color: magenta;"&gt;"&lt;/span&gt;) );&lt;br /&gt;&lt;span style="color: brown;"&gt;11 &lt;/span&gt;&lt;span style="color: brown;"&gt;&lt;b&gt;my&lt;/b&gt;&lt;/span&gt; &lt;span style="color: darkcyan;"&gt;$format&lt;/span&gt;   = &lt;span style="color: darkcyan;"&gt;$q&lt;/span&gt;&lt;span style="color: darkcyan;"&gt;-&amp;gt;param&lt;/span&gt;(&lt;span style="color: magenta;"&gt;"&lt;/span&gt;&lt;span style="color: magenta;"&gt;format&lt;/span&gt;&lt;span style="color: magenta;"&gt;"&lt;/span&gt;) || &lt;span style="color: magenta;"&gt;"&lt;/span&gt;&lt;span style="color: magenta;"&gt;HTML&lt;/span&gt;&lt;span style="color: magenta;"&gt;"&lt;/span&gt;;&lt;br /&gt;&lt;span style="color: brown;"&gt;12 &lt;/span&gt;given (&lt;span style="color: darkcyan;"&gt;$format&lt;/span&gt;) {&lt;br /&gt;&lt;span style="color: brown;"&gt;13 &lt;/span&gt;    when (&lt;span style="color: magenta;"&gt;"&lt;/span&gt;&lt;span style="color: magenta;"&gt;source&lt;/span&gt;&lt;span style="color: magenta;"&gt;"&lt;/span&gt;) {&lt;br /&gt;&lt;span style="color: brown;"&gt;14 &lt;/span&gt;        &lt;span style="color: brown;"&gt;&lt;b&gt;print&lt;/b&gt;&lt;/span&gt; &lt;span style="color: darkcyan;"&gt;$q&lt;/span&gt;&lt;span style="color: darkcyan;"&gt;-&amp;gt;header&lt;/span&gt;(&lt;span style="color: magenta;"&gt;"&lt;/span&gt;&lt;span style="color: magenta;"&gt;text/plain&lt;/span&gt;&lt;span style="color: magenta;"&gt;"&lt;/span&gt;);&lt;br /&gt;&lt;span style="color: brown;"&gt;15 &lt;/span&gt;        &lt;span style="color: brown;"&gt;&lt;b&gt;open&lt;/b&gt;&lt;/span&gt; &lt;span style="color: darkcyan;"&gt;POD&lt;/span&gt;, &lt;span style="color: darkcyan;"&gt;$filename&lt;/span&gt;;&lt;br /&gt;&lt;span style="color: brown;"&gt;16 &lt;/span&gt;        &lt;span style="color: brown;"&gt;&lt;b&gt;print&lt;/b&gt;&lt;/span&gt; &lt;span style="color: darkcyan;"&gt;$_&lt;/span&gt; &lt;span style="color: brown;"&gt;&lt;b&gt;while&lt;/b&gt;&lt;/span&gt; (&lt;span style="color: darkcyan;"&gt;&amp;lt;POD&amp;gt;&lt;/span&gt;);&lt;br /&gt;&lt;span style="color: brown;"&gt;17 &lt;/span&gt;    }&lt;br /&gt;&lt;span style="color: brown;"&gt;18 &lt;/span&gt;    when (&lt;span style="color: magenta;"&gt;'&lt;/span&gt;&lt;span style="color: magenta;"&gt;HTML&lt;/span&gt;&lt;span style="color: magenta;"&gt;'&lt;/span&gt;) {&lt;br /&gt;&lt;span style="color: brown;"&gt;19 &lt;/span&gt;        &lt;span style="color: brown;"&gt;&lt;b&gt;my&lt;/b&gt;&lt;/span&gt; &lt;span style="color: darkcyan;"&gt;$parser&lt;/span&gt; = Pod::Simple::HTML-&amp;gt;&lt;span style="color: brown;"&gt;&lt;b&gt;new&lt;/b&gt;&lt;/span&gt;;&lt;br /&gt;&lt;span style="color: brown;"&gt;20 &lt;/span&gt;        &lt;span style="color: brown;"&gt;&lt;b&gt;print&lt;/b&gt;&lt;/span&gt; &lt;span style="color: darkcyan;"&gt;$q&lt;/span&gt;&lt;span style="color: darkcyan;"&gt;-&amp;gt;header&lt;/span&gt;(&lt;span style="color: magenta;"&gt;"&lt;/span&gt;&lt;span style="color: magenta;"&gt;text/html&lt;/span&gt;&lt;span style="color: magenta;"&gt;"&lt;/span&gt;);&lt;br /&gt;&lt;span style="color: brown;"&gt;21 &lt;/span&gt;        &lt;span style="color: darkcyan;"&gt;$parser&lt;/span&gt;&lt;span style="color: darkcyan;"&gt;-&amp;gt;perldoc_url_prefix&lt;/span&gt;( &lt;span style="color: darkcyan;"&gt;$q&lt;/span&gt;&lt;span style="color: darkcyan;"&gt;-&amp;gt;url&lt;/span&gt;( -&lt;span style="color: magenta;"&gt;path_info &lt;/span&gt;=&amp;gt; &lt;span style="color: magenta;"&gt;1&lt;/span&gt; ) . &lt;span style="color: magenta;"&gt;"&lt;/span&gt;&lt;span style="color: magenta;"&gt;?pod=&lt;/span&gt;&lt;span style="color: magenta;"&gt;"&lt;/span&gt; );&lt;br /&gt;&lt;span style="color: brown;"&gt;22 &lt;/span&gt;        &lt;span style="color: brown;"&gt;&lt;b&gt;my&lt;/b&gt;&lt;/span&gt; &lt;span style="color: darkcyan;"&gt;$footer&lt;/span&gt; = &lt;span style="color: magenta;"&gt;"&lt;/span&gt;&lt;span style="color: magenta;"&gt;&amp;lt;hr&amp;gt;&lt;/span&gt;&lt;span style="color: magenta;"&gt;"&lt;/span&gt; . make_link(&lt;span style="color: magenta;"&gt;"&lt;/span&gt;&lt;span style="color: magenta;"&gt;source&lt;/span&gt;&lt;span style="color: magenta;"&gt;"&lt;/span&gt;);&lt;br /&gt;&lt;span style="color: brown;"&gt;23 &lt;/span&gt;        &lt;span style="color: darkcyan;"&gt;$parser&lt;/span&gt;&lt;span style="color: darkcyan;"&gt;-&amp;gt;html_footer&lt;/span&gt;(qq[\n&amp;lt;!-- end doc --&amp;gt;\n\n&lt;span style="color: darkcyan;"&gt;$footer&lt;/span&gt;&amp;lt;/body&amp;gt;&amp;lt;/html&amp;gt;\n]);&lt;br /&gt;&lt;span style="color: brown;"&gt;24 &lt;/span&gt;        &lt;span style="color: darkcyan;"&gt;$parser&lt;/span&gt;&lt;span style="color: darkcyan;"&gt;-&amp;gt;output_fh&lt;/span&gt;(*STDOUT);&lt;br /&gt;&lt;span style="color: brown;"&gt;25 &lt;/span&gt;        &lt;span style="color: darkcyan;"&gt;$parser&lt;/span&gt;&lt;span style="color: darkcyan;"&gt;-&amp;gt;parse_file&lt;/span&gt;(&lt;span style="color: darkcyan;"&gt;$filename&lt;/span&gt;);&lt;br /&gt;&lt;span style="color: brown;"&gt;26 &lt;/span&gt;    }&lt;br /&gt;&lt;span style="color: brown;"&gt;27 &lt;/span&gt;    default {&lt;br /&gt;&lt;span style="color: brown;"&gt;28 &lt;/span&gt;        &lt;span style="color: brown;"&gt;&lt;b&gt;die&lt;/b&gt;&lt;/span&gt;(&lt;span style="color: magenta;"&gt;"&lt;/span&gt;&lt;span style="color: magenta;"&gt;Formato desconocido '&lt;/span&gt;&lt;span style="color: darkcyan;"&gt;$format&lt;/span&gt;&lt;span style="color: magenta;"&gt;'&lt;/span&gt;&lt;span style="color: magenta;"&gt;"&lt;/span&gt;);&lt;br /&gt;&lt;span style="color: brown;"&gt;29 &lt;/span&gt;    }&lt;br /&gt;&lt;span style="color: brown;"&gt;30 &lt;/span&gt;}&lt;br /&gt;&lt;span style="color: brown;"&gt;31 &lt;/span&gt;&lt;br /&gt;&lt;span style="color: brown;"&gt;32 &lt;/span&gt;&lt;span style="color: brown;"&gt;&lt;b&gt;sub&lt;/b&gt;&lt;/span&gt;&lt;span style="color: darkcyan;"&gt; &lt;/span&gt;&lt;span style="color: darkcyan;"&gt;make_link &lt;/span&gt;{&lt;br /&gt;&lt;span style="color: brown;"&gt;33 &lt;/span&gt;    &lt;span style="color: brown;"&gt;&lt;b&gt;my&lt;/b&gt;&lt;/span&gt; &lt;span style="color: darkcyan;"&gt;$fmt&lt;/span&gt; = &lt;span style="color: brown;"&gt;&lt;b&gt;shift&lt;/b&gt;&lt;/span&gt;;&lt;br /&gt;&lt;span style="color: brown;"&gt;34 &lt;/span&gt;    &lt;span style="color: darkcyan;"&gt;$q&lt;/span&gt;&lt;span style="color: darkcyan;"&gt;-&amp;gt;a&lt;/span&gt;( { &lt;span style="color: magenta;"&gt;href &lt;/span&gt;=&amp;gt; &lt;span style="color: darkcyan;"&gt;$q&lt;/span&gt;&lt;span style="color: darkcyan;"&gt;-&amp;gt;url&lt;/span&gt;( -&lt;span style="color: magenta;"&gt;path_info &lt;/span&gt;=&amp;gt; &lt;span style="color: magenta;"&gt;1&lt;/span&gt;, -&lt;span style="color: magenta;"&gt;query &lt;/span&gt;=&amp;gt; &lt;span style="color: magenta;"&gt;1&lt;/span&gt; ) . &lt;span style="color: magenta;"&gt;"&lt;/span&gt;&lt;span style="color: slateblue;"&gt;\&amp;amp;&lt;/span&gt;&lt;span style="color: magenta;"&gt;format=&lt;/span&gt;&lt;span style="color: darkcyan;"&gt;$fmt&lt;/span&gt;&lt;span style="color: magenta;"&gt;"&lt;/span&gt; }, &lt;span style="color: darkcyan;"&gt;$fmt&lt;/span&gt; );&lt;br /&gt;&lt;span style="color: brown;"&gt;35 &lt;/span&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;Más del doble de las líneas de la versión anterior, sin embargo esta arquitectura muy pronto mostrará ser flexible en combinación con &lt;a href="http://search.cpan.org/perldoc?Pod::Simple"&gt;Pod::Simple&lt;/a&gt; y sus amigos. Mostrar las fuentes, en realidad es una tontería, solamente se envía un encabezado (línea 14) y luego el resto del archivo sin transformar.&lt;br /&gt;&lt;br /&gt;La rutina make_link, facilita la creación de enlaces con el nuevo parámetro (format), a partir de la dirección que estamos visitando (ahora incluye también el query), y aunque solo se usa una vez (línea 22), la usaremos más a medida que agreguemos formatos de conversión a la aplicación.&lt;br /&gt;&lt;br /&gt;Otro módulo que usé fue CGI::Carp con la opción "fatalsToBrowser", esto sirve para que los errores del programa se puedan ver en el navegador, si quieres probarlo, solo debes poner un parámetro format con algo desconocido para el programa y verás el mensaje de error en el navegador.&lt;br /&gt;&lt;br /&gt;Una vez dicho esto voy a transformar POD a Wiki, para ello usaré "Pod::Simple::Wiki" que tiene conversores para al menos 9 formatos de wiki diferentes, así que sin importar si usas Mediawiki o Twiki, siempre puedes escribir tus artículos en POD :-)&lt;br /&gt;&lt;br /&gt;Como Perl es dinámico, versatil y fácil voy a agregar todos los formatos de una vez, para lo cual requiero un arreglo con los formatos que voy a soportar (línea 9) y un mapa que me permita asociar cada formato con algún traductor de POD (línea 10):&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;span style="color: brown;"&gt; 1 &lt;/span&gt;&lt;span style="color: #a020f0;"&gt;#!&lt;/span&gt;&lt;span style="color: #a020f0;"&gt;/usr/bin/perl&lt;/span&gt;&lt;br /&gt;&lt;span style="color: brown;"&gt; 2&lt;/span&gt;&lt;br /&gt;&lt;span style="color: brown;"&gt; 3 &lt;/span&gt;&lt;span style="color: #a020f0;"&gt;use &lt;/span&gt;Modern::Perl;&lt;br /&gt;&lt;span style="color: brown;"&gt; 4 &lt;/span&gt;&lt;span style="color: #a020f0;"&gt;use &lt;/span&gt;CGI;&lt;br /&gt;&lt;span style="color: brown;"&gt; 5 &lt;/span&gt;&lt;span style="color: #a020f0;"&gt;use &lt;/span&gt;CGI::Carp &lt;span style="color: magenta;"&gt;'&lt;/span&gt;&lt;span style="color: magenta;"&gt;fatalsToBrowser&lt;/span&gt;&lt;span style="color: magenta;"&gt;'&lt;/span&gt;;&lt;br /&gt;&lt;span style="color: brown;"&gt; 6 &lt;/span&gt;&lt;span style="color: #a020f0;"&gt;use &lt;/span&gt;Pod::Simple::Search;&lt;br /&gt;&lt;span style="color: brown;"&gt; 7 &lt;/span&gt;&lt;span style="color: #a020f0;"&gt;use &lt;/span&gt;Pod::Simple::HTML;&lt;br /&gt;&lt;span style="color: brown;"&gt; 8 &lt;/span&gt;&lt;br /&gt;&lt;span style="color: brown;"&gt; 9 &lt;/span&gt;&lt;span style="color: brown;"&gt;&lt;b&gt;my&lt;/b&gt;&lt;/span&gt; &lt;span style="color: darkcyan;"&gt;@wikis&lt;/span&gt;   = &lt;span style="color: magenta;"&gt;qw(&lt;/span&gt;&lt;span style="color: magenta;"&gt;Usemod Twiki Template Kwiki Confluence Moinmoin Tiddlywiki Mediawiki Textile&lt;/span&gt;&lt;span style="color: magenta;"&gt;)&lt;/span&gt;;&lt;br /&gt;&lt;span style="color: brown;"&gt;10 &lt;/span&gt;&lt;span style="color: brown;"&gt;&lt;b&gt;my&lt;/b&gt;&lt;/span&gt; &lt;span style="color: darkcyan;"&gt;%formats&lt;/span&gt; = (&lt;br /&gt;&lt;span style="color: brown;"&gt;11 &lt;/span&gt;    ( &lt;span style="color: brown;"&gt;&lt;b&gt;map&lt;/b&gt;&lt;/span&gt; { &lt;span style="color: darkcyan;"&gt;$_&lt;/span&gt; =&amp;gt; &lt;span style="color: magenta;"&gt;"&lt;/span&gt;&lt;span style="color: magenta;"&gt;Pod::Simple::Wiki::&lt;/span&gt;&lt;span style="color: darkcyan;"&gt;$_&lt;/span&gt;&lt;span style="color: magenta;"&gt;"&lt;/span&gt; } &lt;span style="color: darkcyan;"&gt;@wikis&lt;/span&gt; )&lt;br /&gt;&lt;span style="color: brown;"&gt;12 &lt;/span&gt;);&lt;br /&gt;&lt;span style="color: brown;"&gt;13 &lt;/span&gt;&lt;br /&gt;&lt;span style="color: brown;"&gt;14 &lt;/span&gt;&lt;span style="color: brown;"&gt;&lt;b&gt;my&lt;/b&gt;&lt;/span&gt; &lt;span style="color: darkcyan;"&gt;$q&lt;/span&gt;        = &lt;span style="color: brown;"&gt;&lt;b&gt;new&lt;/b&gt;&lt;/span&gt; CGI;&lt;br /&gt;&lt;span style="color: brown;"&gt;15 &lt;/span&gt;&lt;span style="color: brown;"&gt;&lt;b&gt;my&lt;/b&gt;&lt;/span&gt; &lt;span style="color: darkcyan;"&gt;$filename&lt;/span&gt; = Pod::Simple::Search-&amp;gt;&lt;span style="color: brown;"&gt;&lt;b&gt;new&lt;/b&gt;&lt;/span&gt;-&amp;gt;inc(&lt;span style="color: magenta;"&gt;1&lt;/span&gt;)-&amp;gt;find( &lt;span style="color: darkcyan;"&gt;$q&lt;/span&gt;&lt;span style="color: darkcyan;"&gt;-&amp;gt;param&lt;/span&gt;(&lt;span style="color: magenta;"&gt;"&lt;/span&gt;&lt;span style="color: magenta;"&gt;pod&lt;/span&gt;&lt;span style="color: magenta;"&gt;"&lt;/span&gt;) );&lt;br /&gt;&lt;span style="color: brown;"&gt;16 &lt;/span&gt;&lt;span style="color: brown;"&gt;&lt;b&gt;my&lt;/b&gt;&lt;/span&gt; &lt;span style="color: darkcyan;"&gt;$format&lt;/span&gt;   = &lt;span style="color: darkcyan;"&gt;$q&lt;/span&gt;&lt;span style="color: darkcyan;"&gt;-&amp;gt;param&lt;/span&gt;(&lt;span style="color: magenta;"&gt;"&lt;/span&gt;&lt;span style="color: magenta;"&gt;format&lt;/span&gt;&lt;span style="color: magenta;"&gt;"&lt;/span&gt;) || &lt;span style="color: magenta;"&gt;"&lt;/span&gt;&lt;span style="color: magenta;"&gt;HTML&lt;/span&gt;&lt;span style="color: magenta;"&gt;"&lt;/span&gt;;&lt;br /&gt;&lt;span style="color: brown;"&gt;17 &lt;/span&gt;given (&lt;span style="color: darkcyan;"&gt;$format&lt;/span&gt;) {&lt;br /&gt;&lt;span style="color: brown;"&gt;18 &lt;/span&gt;    when (&lt;span style="color: magenta;"&gt;"&lt;/span&gt;&lt;span style="color: magenta;"&gt;source&lt;/span&gt;&lt;span style="color: magenta;"&gt;"&lt;/span&gt;) {&lt;br /&gt;&lt;span style="color: brown;"&gt;19 &lt;/span&gt;        &lt;span style="color: brown;"&gt;&lt;b&gt;print&lt;/b&gt;&lt;/span&gt; &lt;span style="color: darkcyan;"&gt;$q&lt;/span&gt;&lt;span style="color: darkcyan;"&gt;-&amp;gt;header&lt;/span&gt;(&lt;span style="color: magenta;"&gt;"&lt;/span&gt;&lt;span style="color: magenta;"&gt;text/plain&lt;/span&gt;&lt;span style="color: magenta;"&gt;"&lt;/span&gt;);&lt;br /&gt;&lt;span style="color: brown;"&gt;20 &lt;/span&gt;        &lt;span style="color: brown;"&gt;&lt;b&gt;open&lt;/b&gt;&lt;/span&gt; &lt;span style="color: darkcyan;"&gt;POD&lt;/span&gt;, &lt;span style="color: darkcyan;"&gt;$filename&lt;/span&gt;;&lt;br /&gt;&lt;span style="color: brown;"&gt;21 &lt;/span&gt;        &lt;span style="color: brown;"&gt;&lt;b&gt;print&lt;/b&gt;&lt;/span&gt; &lt;span style="color: darkcyan;"&gt;$_&lt;/span&gt; &lt;span style="color: brown;"&gt;&lt;b&gt;while&lt;/b&gt;&lt;/span&gt; (&lt;span style="color: darkcyan;"&gt;&amp;lt;POD&amp;gt;&lt;/span&gt;);&lt;br /&gt;&lt;span style="color: brown;"&gt;22 &lt;/span&gt;    }&lt;br /&gt;&lt;span style="color: brown;"&gt;23 &lt;/span&gt;    when (&lt;span style="color: magenta;"&gt;'&lt;/span&gt;&lt;span style="color: magenta;"&gt;HTML&lt;/span&gt;&lt;span style="color: magenta;"&gt;'&lt;/span&gt;) {&lt;br /&gt;&lt;span style="color: brown;"&gt;24 &lt;/span&gt;        &lt;span style="color: brown;"&gt;&lt;b&gt;my&lt;/b&gt;&lt;/span&gt; &lt;span style="color: darkcyan;"&gt;$parser&lt;/span&gt; = Pod::Simple::HTML-&amp;gt;&lt;span style="color: brown;"&gt;&lt;b&gt;new&lt;/b&gt;&lt;/span&gt;;&lt;br /&gt;&lt;span style="color: brown;"&gt;25 &lt;/span&gt;        &lt;span style="color: brown;"&gt;&lt;b&gt;print&lt;/b&gt;&lt;/span&gt; &lt;span style="color: darkcyan;"&gt;$q&lt;/span&gt;&lt;span style="color: darkcyan;"&gt;-&amp;gt;header&lt;/span&gt;(&lt;span style="color: magenta;"&gt;"&lt;/span&gt;&lt;span style="color: magenta;"&gt;text/html&lt;/span&gt;&lt;span style="color: magenta;"&gt;"&lt;/span&gt;);&lt;br /&gt;&lt;span style="color: brown;"&gt;26 &lt;/span&gt;        &lt;span style="color: darkcyan;"&gt;$parser&lt;/span&gt;&lt;span style="color: darkcyan;"&gt;-&amp;gt;perldoc_url_prefix&lt;/span&gt;( &lt;span style="color: darkcyan;"&gt;$q&lt;/span&gt;&lt;span style="color: darkcyan;"&gt;-&amp;gt;url&lt;/span&gt;( -&lt;span style="color: magenta;"&gt;path_info &lt;/span&gt;=&amp;gt; &lt;span style="color: magenta;"&gt;1&lt;/span&gt; ) . &lt;span style="color: magenta;"&gt;"&lt;/span&gt;&lt;span style="color: magenta;"&gt;?pod=&lt;/span&gt;&lt;span style="color: magenta;"&gt;"&lt;/span&gt; );&lt;br /&gt;&lt;span style="color: brown;"&gt;27 &lt;/span&gt;        &lt;span style="color: brown;"&gt;&lt;b&gt;my&lt;/b&gt;&lt;/span&gt; &lt;span style="color: darkcyan;"&gt;$footer&lt;/span&gt; = &lt;span style="color: magenta;"&gt;"&lt;/span&gt;&lt;span style="color: magenta;"&gt;&amp;lt;hr&amp;gt;&lt;/span&gt;&lt;span style="color: magenta;"&gt;"&lt;/span&gt; . make_link(&lt;span style="color: magenta;"&gt;"&lt;/span&gt;&lt;span style="color: magenta;"&gt;source&lt;/span&gt;&lt;span style="color: magenta;"&gt;"&lt;/span&gt;)&lt;br /&gt;&lt;span style="color: brown;"&gt;28 &lt;/span&gt;            . &lt;span style="color: magenta;"&gt;"&lt;/span&gt;&lt;span style="color: magenta;"&gt; | Wiki formats: &lt;/span&gt;&lt;span style="color: magenta;"&gt;"&lt;/span&gt;&lt;br /&gt;&lt;span style="color: brown;"&gt;29 &lt;/span&gt;            . &lt;span style="color: brown;"&gt;&lt;b&gt;join&lt;/b&gt;&lt;/span&gt;( &lt;span style="color: magenta;"&gt;"&lt;/span&gt;&lt;span style="color: magenta;"&gt; &lt;/span&gt;&lt;span style="color: magenta;"&gt;"&lt;/span&gt;, &lt;span style="color: brown;"&gt;&lt;b&gt;map&lt;/b&gt;&lt;/span&gt; { make_link(&lt;span style="color: darkcyan;"&gt;$_&lt;/span&gt;) } &lt;span style="color: darkcyan;"&gt;@wikis&lt;/span&gt; );&lt;br /&gt;&lt;span style="color: brown;"&gt;30 &lt;/span&gt;        &lt;span style="color: darkcyan;"&gt;$parser&lt;/span&gt;&lt;span style="color: darkcyan;"&gt;-&amp;gt;html_footer&lt;/span&gt;(qq[\n&amp;lt;!-- end doc --&amp;gt;\n\n&lt;span style="color: darkcyan;"&gt;$footer&lt;/span&gt;&amp;lt;/body&amp;gt;&amp;lt;/html&amp;gt;\n]);&lt;br /&gt;&lt;span style="color: brown;"&gt;31 &lt;/span&gt;        &lt;span style="color: darkcyan;"&gt;$parser&lt;/span&gt;&lt;span style="color: darkcyan;"&gt;-&amp;gt;output_fh&lt;/span&gt;(*STDOUT);&lt;br /&gt;&lt;span style="color: brown;"&gt;32 &lt;/span&gt;        &lt;span style="color: darkcyan;"&gt;$parser&lt;/span&gt;&lt;span style="color: darkcyan;"&gt;-&amp;gt;parse_file&lt;/span&gt;(&lt;span style="color: darkcyan;"&gt;$filename&lt;/span&gt;);&lt;br /&gt;&lt;span style="color: brown;"&gt;33 &lt;/span&gt;    }&lt;br /&gt;&lt;span style="color: brown;"&gt;34 &lt;/span&gt;    when (&lt;span style="color: darkcyan;"&gt;%formats&lt;/span&gt;) {&lt;br /&gt;&lt;span style="color: brown;"&gt;35 &lt;/span&gt;        &lt;span style="color: brown;"&gt;&lt;b&gt;my&lt;/b&gt;&lt;/span&gt; &lt;span style="color: darkcyan;"&gt;$class&lt;/span&gt; = &lt;span style="color: darkcyan;"&gt;$formats{$format}&lt;/span&gt;;&lt;br /&gt;&lt;span style="color: brown;"&gt;36 &lt;/span&gt;        &lt;span style="color: brown;"&gt;&lt;b&gt;eval&lt;/b&gt;&lt;/span&gt; &lt;span style="color: magenta;"&gt;"&lt;/span&gt;&lt;span style="color: magenta;"&gt;require &lt;/span&gt;&lt;span style="color: darkcyan;"&gt;$class&lt;/span&gt;&lt;span style="color: magenta;"&gt;"&lt;/span&gt;;&lt;br /&gt;&lt;span style="color: brown;"&gt;37 &lt;/span&gt;        &lt;span style="color: brown;"&gt;&lt;b&gt;print&lt;/b&gt;&lt;/span&gt; &lt;span style="color: darkcyan;"&gt;$q&lt;/span&gt;&lt;span style="color: darkcyan;"&gt;-&amp;gt;header&lt;/span&gt;( &lt;span style="color: magenta;"&gt;"&lt;/span&gt;&lt;span style="color: magenta;"&gt;text/plain&lt;/span&gt;&lt;span style="color: magenta;"&gt;"&lt;/span&gt; );&lt;br /&gt;&lt;span style="color: brown;"&gt;38 &lt;/span&gt;        &lt;span style="color: darkcyan;"&gt;$class&lt;/span&gt;&lt;span style="color: darkcyan;"&gt;-&amp;gt;filter&lt;/span&gt;(&lt;span style="color: darkcyan;"&gt;$filename&lt;/span&gt;);&lt;br /&gt;&lt;span style="color: brown;"&gt;39 &lt;/span&gt;    }&lt;br /&gt;&lt;span style="color: brown;"&gt;40 &lt;/span&gt;    default {&lt;br /&gt;&lt;span style="color: brown;"&gt;41 &lt;/span&gt;        &lt;span style="color: brown;"&gt;&lt;b&gt;die&lt;/b&gt;&lt;/span&gt;(&lt;span style="color: magenta;"&gt;"&lt;/span&gt;&lt;span style="color: magenta;"&gt;Formato desconocido '&lt;/span&gt;&lt;span style="color: darkcyan;"&gt;$format&lt;/span&gt;&lt;span style="color: magenta;"&gt;'&lt;/span&gt;&lt;span style="color: magenta;"&gt;"&lt;/span&gt;);&lt;br /&gt;&lt;span style="color: brown;"&gt;42 &lt;/span&gt;    }&lt;br /&gt;&lt;span style="color: brown;"&gt;43 &lt;/span&gt;}&lt;br /&gt;&lt;span style="color: brown;"&gt;44 &lt;/span&gt;&lt;br /&gt;&lt;span style="color: brown;"&gt;45 &lt;/span&gt;&lt;span style="color: brown;"&gt;&lt;b&gt;sub&lt;/b&gt;&lt;/span&gt;&lt;span style="color: darkcyan;"&gt; &lt;/span&gt;&lt;span style="color: darkcyan;"&gt;make_link &lt;/span&gt;{&lt;br /&gt;&lt;span style="color: brown;"&gt;46 &lt;/span&gt;    &lt;span style="color: brown;"&gt;&lt;b&gt;my&lt;/b&gt;&lt;/span&gt; &lt;span style="color: darkcyan;"&gt;$fmt&lt;/span&gt; = &lt;span style="color: brown;"&gt;&lt;b&gt;shift&lt;/b&gt;&lt;/span&gt;;&lt;br /&gt;&lt;span style="color: brown;"&gt;47 &lt;/span&gt;    &lt;span style="color: darkcyan;"&gt;$q&lt;/span&gt;&lt;span style="color: darkcyan;"&gt;-&amp;gt;a&lt;/span&gt;( { &lt;span style="color: magenta;"&gt;href &lt;/span&gt;=&amp;gt; &lt;span style="color: darkcyan;"&gt;$q&lt;/span&gt;&lt;span style="color: darkcyan;"&gt;-&amp;gt;url&lt;/span&gt;( -&lt;span style="color: magenta;"&gt;path_info &lt;/span&gt;=&amp;gt; &lt;span style="color: magenta;"&gt;1&lt;/span&gt;, -&lt;span style="color: magenta;"&gt;query &lt;/span&gt;=&amp;gt; &lt;span style="color: magenta;"&gt;1&lt;/span&gt; ) . &lt;span style="color: magenta;"&gt;"&lt;/span&gt;&lt;span style="color: slateblue;"&gt;\&amp;amp;&lt;/span&gt;&lt;span style="color: magenta;"&gt;format=&lt;/span&gt;&lt;span style="color: darkcyan;"&gt;$fmt&lt;/span&gt;&lt;span style="color: magenta;"&gt;"&lt;/span&gt; }, &lt;span style="color: darkcyan;"&gt;$fmt&lt;/span&gt; );&lt;br /&gt;&lt;span style="color: brown;"&gt;48 &lt;/span&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;Todo el trabajo se hace al reconocer alguno de los nuevos formatos en la línea 34, allí obtenemos la clase de "Pod::Simple::Wiki" que implementa la conversión y la cargamos dinámicamente con require dentro de un eval (línea 36), de esta manera no tendremos que cargar todas las clases al principio de nuestro programa, utilizando sólo lo necesario para la conversión deseada, luego se envía el tipo de contenidos al navegador y se hace la conversión según clase de wiki deseado.&lt;br /&gt;&lt;br /&gt;Ahora solo queda incluir los enlaces a los diferentes formatos en el footer, lo que se hace durante la generación de la página en HTML (líneas 27 a 29).&lt;br /&gt;&lt;br /&gt;Si quisieras incluir parte de la documentación en un manual impreso probablemente querrás convertir POD, para las herramientas más adaptadas a este trabajo, vamos a generar RTF y LaTeX a partir de POD, no debe ser muy difícil porque ya existen las clases en el CPAN, lo primero es generalizar&amp;nbsp; el tipo de contenido enviado al navegador, permitiendo usar el mismo código para diversos formatos:&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;span style="color: brown;"&gt;37 &lt;/span&gt;        &lt;span style="color: brown;"&gt;&lt;b&gt;print&lt;/b&gt;&lt;/span&gt; &lt;span style="color: darkcyan;"&gt;$q&lt;/span&gt;&lt;span style="color: darkcyan;"&gt;-&amp;gt;header&lt;/span&gt;( &lt;span style="color: darkcyan;"&gt;$content_types{$format}&lt;/span&gt; || &lt;span style="color: magenta;"&gt;"&lt;/span&gt;&lt;span style="color: magenta;"&gt;text/plain&lt;/span&gt;&lt;span style="color: magenta;"&gt;"&lt;/span&gt; );&lt;/pre&gt;&lt;br /&gt;Esto asume que existe un hash que tiene los formatos que manejaremos asociados a sus tipos de contenido, utilizaremos también este mapa para&amp;nbsp; generar los enlaces a los nuevos tipos de contenido:&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;span style="color: brown;"&gt;27 &lt;/span&gt;        &lt;span style="color: brown;"&gt;&lt;b&gt;my&lt;/b&gt;&lt;/span&gt; &lt;span style="color: darkcyan;"&gt;$footer&lt;/span&gt; = &lt;span style="color: magenta;"&gt;"&lt;/span&gt;&lt;span style="color: magenta;"&gt;&amp;lt;hr&amp;gt;&lt;/span&gt;&lt;span style="color: magenta;"&gt;"&lt;/span&gt; . make_link(&lt;span style="color: magenta;"&gt;"&lt;/span&gt;&lt;span style="color: magenta;"&gt;source&lt;/span&gt;&lt;span style="color: magenta;"&gt;"&lt;/span&gt;)&lt;br /&gt;&lt;span style="color: brown;"&gt;28 &lt;/span&gt;            . &lt;span style="color: brown;"&gt;&lt;b&gt;join&lt;/b&gt;&lt;/span&gt;( &lt;span style="color: magenta;"&gt;"&lt;/span&gt;&lt;span style="color: magenta;"&gt; | &lt;/span&gt;&lt;span style="color: magenta;"&gt;"&lt;/span&gt;, &lt;span style="color: brown;"&gt;&lt;b&gt;map&lt;/b&gt;&lt;/span&gt; { make_link(&lt;span style="color: darkcyan;"&gt;$_&lt;/span&gt;) } &lt;span style="color: brown;"&gt;&lt;b&gt;keys&lt;/b&gt;&lt;/span&gt; &lt;span style="color: darkcyan;"&gt;%content_types&lt;/span&gt; )&lt;br /&gt;&lt;span style="color: brown;"&gt;29 &lt;/span&gt;            . &lt;span style="color: magenta;"&gt;"&lt;/span&gt;&lt;span style="color: magenta;"&gt; Wiki formats: &lt;/span&gt;&lt;span style="color: magenta;"&gt;"&lt;/span&gt;&lt;br /&gt;&lt;span style="color: brown;"&gt;30 &lt;/span&gt;            . &lt;span style="color: brown;"&gt;&lt;b&gt;join&lt;/b&gt;&lt;/span&gt;( &lt;span style="color: magenta;"&gt;"&lt;/span&gt;&lt;span style="color: magenta;"&gt; | &lt;/span&gt;&lt;span style="color: magenta;"&gt;"&lt;/span&gt;, &lt;span style="color: brown;"&gt;&lt;b&gt;map&lt;/b&gt;&lt;/span&gt; { make_link(&lt;span style="color: darkcyan;"&gt;$_&lt;/span&gt;) } &lt;span style="color: darkcyan;"&gt;@wikis&lt;/span&gt; );&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;El mapa de formatos y tipos de contenido se puede agregar al principio:&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;span style="color: brown;"&gt; 9 &lt;/span&gt;&lt;span style="color: brown;"&gt;&lt;b&gt;my&lt;/b&gt;&lt;/span&gt; &lt;span style="color: darkcyan;"&gt;%content_types&lt;/span&gt; = (&lt;br /&gt;&lt;span style="color: brown;"&gt;10 &lt;/span&gt;    &lt;span style="color: magenta;"&gt;RTF    &lt;/span&gt;=&amp;gt; &lt;span style="color: magenta;"&gt;"&lt;/span&gt;&lt;span style="color: magenta;"&gt;application/rtf&lt;/span&gt;&lt;span style="color: magenta;"&gt;"&lt;/span&gt;,&lt;br /&gt;&lt;span style="color: brown;"&gt;11 &lt;/span&gt;    &lt;span style="color: magenta;"&gt;LaTeX  &lt;/span&gt;=&amp;gt; &lt;span style="color: magenta;"&gt;"&lt;/span&gt;&lt;span style="color: magenta;"&gt;application/x-latex&lt;/span&gt;&lt;span style="color: magenta;"&gt;"&lt;/span&gt;,&lt;br /&gt;&lt;span style="color: brown;"&gt;12 &lt;/span&gt;);&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;y no olvidemos que todo formato debe estar asociado a la clase que hace la conversión en %formats, de lo contrario el formato no será reconocido en el given:&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;span style="color: brown;"&gt;1&lt;/span&gt;&lt;span style="color: brown;"&gt;4 &lt;/span&gt;&lt;span style="color: brown;"&gt;&lt;b&gt;my&lt;/b&gt;&lt;/span&gt; &lt;span style="color: darkcyan;"&gt;%formats&lt;/span&gt; = (&lt;br /&gt;&lt;span style="color: brown;"&gt;15 &lt;/span&gt;    ( &lt;span style="color: brown;"&gt;&lt;b&gt;map&lt;/b&gt;&lt;/span&gt; { &lt;span style="color: darkcyan;"&gt;$_&lt;/span&gt; =&amp;gt; &lt;span style="color: magenta;"&gt;"&lt;/span&gt;&lt;span style="color: magenta;"&gt;Pod::Simple::&lt;/span&gt;&lt;span style="color: darkcyan;"&gt;$_&lt;/span&gt;&lt;span style="color: magenta;"&gt;"&lt;/span&gt; } &lt;span style="color: brown;"&gt;&lt;b&gt;keys&lt;/b&gt;&lt;/span&gt; &lt;span style="color: darkcyan;"&gt;%content_types&lt;/span&gt; ),&lt;br /&gt;&lt;span style="color: brown;"&gt;16 &lt;/span&gt;    ( &lt;span style="color: brown;"&gt;&lt;b&gt;map&lt;/b&gt;&lt;/span&gt; { &lt;span style="color: darkcyan;"&gt;$_&lt;/span&gt; =&amp;gt; &lt;span style="color: magenta;"&gt;"&lt;/span&gt;&lt;span style="color: magenta;"&gt;Pod::Simple::Wiki::&lt;/span&gt;&lt;span style="color: darkcyan;"&gt;$_&lt;/span&gt;&lt;span style="color: magenta;"&gt;"&lt;/span&gt; } &lt;span style="color: darkcyan;"&gt;@wikis&lt;/span&gt; )&lt;br /&gt;&lt;span style="color: brown;"&gt;17 &lt;/span&gt;);&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;Ahora podemos convertir a RTF, lo que seguramente arrancará tu suite de oficina favorita, y en el caso de LaTeX probablemente se descargará el archivo.&lt;br /&gt;&lt;br /&gt;Para cerrar, voy a incluir un último formato: PDF, este será más complejo porque no hay un módulo en el CPAN que transforme POD a PDF, por ello voy a hacerme uno, basado en Pod::Simple (línea 5), que use LaTeX como formato intermedio para crear los PDF.&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;span style="color: brown;"&gt; 1 &lt;/span&gt;&lt;span style="color: brown;"&gt;&lt;b&gt;package&lt;/b&gt;&lt;/span&gt;&lt;span style="color: seagreen;"&gt;&lt;b&gt; Pod::Simple::PDF;&lt;/b&gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="color: brown;"&gt; 2 &lt;/span&gt;&lt;br /&gt;&lt;span style="color: brown;"&gt; 3 &lt;/span&gt;&lt;span style="color: #a020f0;"&gt;use &lt;/span&gt;Modern::Perl;&lt;br /&gt;&lt;span style="color: brown;"&gt; 4 &lt;/span&gt;&lt;span style="color: #a020f0;"&gt;use &lt;/span&gt;Pod::Simple::LaTeX;&lt;br /&gt;&lt;span style="color: brown;"&gt; 5 &lt;/span&gt;&lt;span style="color: #a020f0;"&gt;use base&lt;/span&gt; &lt;span style="color: magenta;"&gt;"&lt;/span&gt;&lt;span style="color: magenta;"&gt;Pod::Simple&lt;/span&gt;&lt;span style="color: magenta;"&gt;"&lt;/span&gt;;&lt;br /&gt;&lt;span style="color: brown;"&gt; 6 &lt;/span&gt;&lt;br /&gt;&lt;span style="color: brown;"&gt; 7 &lt;/span&gt;&lt;span style="color: #a020f0;"&gt;use &lt;/span&gt;File::Temp;&lt;br /&gt;&lt;span style="color: brown;"&gt; 8 &lt;/span&gt;&lt;span style="color: #a020f0;"&gt;use &lt;/span&gt;File::Spec::Functions;&lt;br /&gt;&lt;span style="color: brown;"&gt; 9 &lt;/span&gt;&lt;span style="color: #a020f0;"&gt;use &lt;/span&gt;IO::File;&lt;br /&gt;&lt;span style="color: brown;"&gt;10 &lt;/span&gt;&lt;span style="color: #a020f0;"&gt;use &lt;/span&gt;IO::Handle;&lt;br /&gt;&lt;span style="color: brown;"&gt;11 &lt;/span&gt;&lt;br /&gt;&lt;span style="color: brown;"&gt;12 &lt;/span&gt;&lt;span style="color: brown;"&gt;&lt;b&gt;sub&lt;/b&gt;&lt;/span&gt;&lt;span style="color: darkcyan;"&gt; &lt;/span&gt;&lt;span style="color: darkcyan;"&gt;new &lt;/span&gt;{&lt;br /&gt;&lt;span style="color: brown;"&gt;13 &lt;/span&gt;    &lt;span style="color: brown;"&gt;&lt;b&gt;my&lt;/b&gt;&lt;/span&gt; &lt;span style="color: darkcyan;"&gt;$class&lt;/span&gt; = &lt;span style="color: brown;"&gt;&lt;b&gt;shift&lt;/b&gt;&lt;/span&gt;;&lt;br /&gt;&lt;span style="color: brown;"&gt;14 &lt;/span&gt;    &lt;span style="color: brown;"&gt;&lt;b&gt;return&lt;/b&gt;&lt;/span&gt; &lt;span style="color: brown;"&gt;&lt;b&gt;bless&lt;/b&gt;&lt;/span&gt; { &lt;span style="color: magenta;"&gt;output_fh &lt;/span&gt;=&amp;gt; \*STDOUT }, &lt;span style="color: brown;"&gt;&lt;b&gt;ref&lt;/b&gt;&lt;/span&gt; &lt;span style="color: darkcyan;"&gt;$class&lt;/span&gt; || &lt;span style="color: darkcyan;"&gt;$class&lt;/span&gt;;&lt;br /&gt;&lt;span style="color: brown;"&gt;15 &lt;/span&gt;}&lt;br /&gt;&lt;span style="color: brown;"&gt;16 &lt;/span&gt;&lt;br /&gt;&lt;span style="color: brown;"&gt;17 &lt;/span&gt;&lt;span style="color: brown;"&gt;&lt;b&gt;sub&lt;/b&gt;&lt;/span&gt;&lt;span style="color: darkcyan;"&gt; &lt;/span&gt;&lt;span style="color: darkcyan;"&gt;parse_file &lt;/span&gt;{&lt;br /&gt;&lt;span style="color: brown;"&gt;18 &lt;/span&gt;    &lt;span style="color: brown;"&gt;&lt;b&gt;my&lt;/b&gt;&lt;/span&gt; &lt;span style="color: darkcyan;"&gt;$self&lt;/span&gt; = &lt;span style="color: brown;"&gt;&lt;b&gt;shift&lt;/b&gt;&lt;/span&gt;;&lt;br /&gt;&lt;span style="color: brown;"&gt;19 &lt;/span&gt;    &lt;span style="color: brown;"&gt;&lt;b&gt;my&lt;/b&gt;&lt;/span&gt; &lt;span style="color: darkcyan;"&gt;$file&lt;/span&gt; = &lt;span style="color: brown;"&gt;&lt;b&gt;shift&lt;/b&gt;&lt;/span&gt;;&lt;br /&gt;&lt;span style="color: brown;"&gt;20 &lt;/span&gt;&lt;br /&gt;&lt;span style="color: brown;"&gt;21 &lt;/span&gt;    &lt;span style="color: brown;"&gt;&lt;b&gt;my&lt;/b&gt;&lt;/span&gt; &lt;span style="color: darkcyan;"&gt;$dir&lt;/span&gt;      = File::Temp-&amp;gt;newdir();&lt;br /&gt;&lt;span style="color: brown;"&gt;22 &lt;/span&gt;    &lt;span style="color: brown;"&gt;&lt;b&gt;my&lt;/b&gt;&lt;/span&gt; &lt;span style="color: darkcyan;"&gt;$tex_name&lt;/span&gt; = catfile( &lt;span style="color: darkcyan;"&gt;$dir&lt;/span&gt;, &lt;span style="color: magenta;"&gt;"&lt;/span&gt;&lt;span style="color: magenta;"&gt;pod.tex&lt;/span&gt;&lt;span style="color: magenta;"&gt;"&lt;/span&gt; );&lt;br /&gt;&lt;span style="color: brown;"&gt;23 &lt;/span&gt;    &lt;span style="color: brown;"&gt;&lt;b&gt;my&lt;/b&gt;&lt;/span&gt; &lt;span style="color: darkcyan;"&gt;$texf&lt;/span&gt;     = IO::File-&amp;gt;&lt;span style="color: brown;"&gt;&lt;b&gt;new&lt;/b&gt;&lt;/span&gt;( &lt;span style="color: darkcyan;"&gt;$tex_name&lt;/span&gt;, &lt;span style="color: magenta;"&gt;"&lt;/span&gt;&lt;span style="color: magenta;"&gt;w&lt;/span&gt;&lt;span style="color: magenta;"&gt;"&lt;/span&gt; );&lt;br /&gt;&lt;span style="color: brown;"&gt;24 &lt;/span&gt;    &lt;span style="color: brown;"&gt;&lt;b&gt;my&lt;/b&gt;&lt;/span&gt; &lt;span style="color: darkcyan;"&gt;$parser&lt;/span&gt;   = Pod::Simple::LaTeX-&amp;gt;&lt;span style="color: brown;"&gt;&lt;b&gt;new&lt;/b&gt;&lt;/span&gt;;&lt;br /&gt;&lt;span style="color: brown;"&gt;25 &lt;/span&gt;    &lt;span style="color: darkcyan;"&gt;$parser&lt;/span&gt;&lt;span style="color: darkcyan;"&gt;-&amp;gt;output_fh&lt;/span&gt;(&lt;span style="color: darkcyan;"&gt;$texf&lt;/span&gt;);&lt;br /&gt;&lt;span style="color: brown;"&gt;26 &lt;/span&gt;    &lt;span style="color: darkcyan;"&gt;$parser&lt;/span&gt;&lt;span style="color: darkcyan;"&gt;-&amp;gt;parse_file&lt;/span&gt;(&lt;span style="color: darkcyan;"&gt;$file&lt;/span&gt;);&lt;br /&gt;&lt;span style="color: brown;"&gt;27 &lt;/span&gt;    &lt;span style="color: darkcyan;"&gt;$texf&lt;/span&gt;&lt;span style="color: darkcyan;"&gt;-&amp;gt;close&lt;/span&gt;;&lt;br /&gt;&lt;span style="color: brown;"&gt;28 &lt;/span&gt;    &lt;span style="color: brown;"&gt;&lt;b&gt;`&lt;/b&gt;&lt;/span&gt;&lt;span style="color: magenta;"&gt;cd '&lt;/span&gt;&lt;span style="color: darkcyan;"&gt;$dir&lt;/span&gt;&lt;span style="color: magenta;"&gt;'; pdflatex '&lt;/span&gt;&lt;span style="color: darkcyan;"&gt;$tex_name&lt;/span&gt;&lt;span style="color: magenta;"&gt;'; pdflatex '&lt;/span&gt;&lt;span style="color: darkcyan;"&gt;$tex_name&lt;/span&gt;&lt;span style="color: magenta;"&gt;'&lt;/span&gt;&lt;span style="color: brown;"&gt;&lt;b&gt;`&lt;/b&gt;&lt;/span&gt;;&lt;br /&gt;&lt;span style="color: brown;"&gt;29 &lt;/span&gt;    &lt;span style="color: brown;"&gt;&lt;b&gt;my&lt;/b&gt;&lt;/span&gt; &lt;span style="color: darkcyan;"&gt;$in&lt;/span&gt; = IO::File-&amp;gt;&lt;span style="color: brown;"&gt;&lt;b&gt;new&lt;/b&gt;&lt;/span&gt;( catfile( &lt;span style="color: darkcyan;"&gt;$dir&lt;/span&gt;, &lt;span style="color: magenta;"&gt;"&lt;/span&gt;&lt;span style="color: magenta;"&gt;pod.pdf&lt;/span&gt;&lt;span style="color: magenta;"&gt;"&lt;/span&gt; ), &lt;span style="color: magenta;"&gt;"&lt;/span&gt;&lt;span style="color: magenta;"&gt;r&lt;/span&gt;&lt;span style="color: magenta;"&gt;"&lt;/span&gt; );&lt;br /&gt;&lt;span style="color: brown;"&gt;30 &lt;/span&gt;    &lt;span style="color: darkcyan;"&gt;$self-&amp;gt;{&lt;/span&gt;&lt;span style="color: magenta;"&gt;'&lt;/span&gt;&lt;span style="color: magenta;"&gt;output_fh&lt;/span&gt;&lt;span style="color: magenta;"&gt;'&lt;/span&gt;&lt;span style="color: darkcyan;"&gt;}&lt;/span&gt;-&amp;gt;&lt;span style="color: brown;"&gt;&lt;b&gt;print&lt;/b&gt;&lt;/span&gt;(&lt;span style="color: darkcyan;"&gt;$_&lt;/span&gt;) &lt;span style="color: brown;"&gt;&lt;b&gt;while&lt;/b&gt;&lt;/span&gt; &lt;span style="color: brown;"&gt;&lt;b&gt;readline&lt;/b&gt;&lt;/span&gt;(&lt;span style="color: darkcyan;"&gt;$in&lt;/span&gt;);&lt;br /&gt;&lt;span style="color: brown;"&gt;31 &lt;/span&gt;}&lt;br /&gt;&lt;span style="color: brown;"&gt;32 &lt;/span&gt;&lt;br /&gt;&lt;span style="color: brown;"&gt;33 &lt;/span&gt;&lt;span style="color: magenta;"&gt;1&lt;/span&gt;;&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;Tal vez la razón por la cual no hay conversor a PDF es porque no hay una manera muy portable de hacerlo, yo voy usar la herramienta pdflatex que es parte de &lt;a href="http://tex%20live/"&gt;TeX Live&lt;/a&gt;, porque supongo que se puede instalar tanto en Unix como en Windows, sin embargo cualquier distribución moderna de TeX en unix debería incluir esta herramienta.&lt;br /&gt;&lt;br /&gt;El método parse_file crea un directorio temporal usando &lt;code&gt;File::Temp-&amp;gt;newdir&lt;/code&gt;&lt;br /&gt;para luego crear el archivo pod.tex dentro del directorio, que se usa para almacenar el resultado de la conversión realizada con &lt;code&gt;Pod::Simple::LaTeX&lt;/code&gt;, este archivo ahora se procesa con el comando 'pdflatex' (línea 27) que produce el archivo 'pod.pdf' (y uno que otro archivo inútil) en el directorio temporal.&lt;br /&gt;&lt;br /&gt;Muchas cosas pueden salir mal durante en la línea 27 porque el método simple que estoy ofrece muy poco control sobre lo que allí sucede, en una implementación mejorada habría que usar módulos como &lt;a href="http://search.cpan.org/perldoc?IPC::Run3"&gt;IPC::Run3&lt;/a&gt; para controlar la ejecución de las herramientas y actuar correctamente ante las diversas fallas que pudieran ocurrir, sin embargo una de las caracteristicas interesantes de Perl es que se pueden hacer prototipos como este rápidamente y después se pueden refinar.&lt;br /&gt;&lt;br /&gt;En las líneas 28 y 29 se transmite 'pod.pdf' al navegador, y al terminar el método parse file, la variable $dir sale de contexto y el objeto File::Temp se destruye, eliminando el directorio temporal y todo lo que este dentro del mismo.&lt;br /&gt;&lt;br /&gt;Una vez que este módulo se guarda en el lugar apropiado, lo que hace automáticamente el CPAN si el módulo esta empaquetado según las instrucciones de &lt;a href="http://perldoc.perl.org/perlmodlib.html"&gt;perlmodlib&lt;/a&gt; (aunque ahora solo para probar puedes poner el archivo PDF.pm en el mismo directorio donde se encuentra el archivo HTML.pm que contiene Pod::Simple::HTML).&lt;br /&gt;&lt;br /&gt;Finalmente hay que agregar el nuevo tipo de contenido (PDF) a la aplicación lo cual es tan simple como agregar una sola línea al hash %content_types (línea 12) sin necesidad de tocar mas nada, ya tenemos un servidor capaz de mostrar POD en mas de una docena de formatos:&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;span style="color: brown;"&gt; 1 &lt;/span&gt;&lt;span style="color: #a020f0;"&gt;#!&lt;/span&gt;&lt;span style="color: #a020f0;"&gt;/usr/bin/perl&lt;/span&gt;&lt;br /&gt;&lt;span style="color: brown;"&gt; 2 &lt;/span&gt;&lt;br /&gt;&lt;span style="color: brown;"&gt; 3 &lt;/span&gt;&lt;span style="color: #a020f0;"&gt;use &lt;/span&gt;Modern::Perl;&lt;br /&gt;&lt;span style="color: brown;"&gt; 4 &lt;/span&gt;&lt;span style="color: #a020f0;"&gt;use &lt;/span&gt;CGI;&lt;br /&gt;&lt;span style="color: brown;"&gt; 5 &lt;/span&gt;&lt;span style="color: #a020f0;"&gt;use &lt;/span&gt;CGI::Carp &lt;span style="color: magenta;"&gt;'&lt;/span&gt;&lt;span style="color: magenta;"&gt;fatalsToBrowser&lt;/span&gt;&lt;span style="color: magenta;"&gt;'&lt;/span&gt;;&lt;br /&gt;&lt;span style="color: brown;"&gt; 6 &lt;/span&gt;&lt;span style="color: #a020f0;"&gt;use &lt;/span&gt;Pod::Simple::Search;&lt;br /&gt;&lt;span style="color: brown;"&gt; 7 &lt;/span&gt;&lt;span style="color: #a020f0;"&gt;use &lt;/span&gt;Pod::Simple::HTML;&lt;br /&gt;&lt;span style="color: brown;"&gt; 8 &lt;/span&gt;&lt;br /&gt;&lt;span style="color: brown;"&gt; 9 &lt;/span&gt;&lt;span style="color: brown;"&gt;&lt;b&gt;my&lt;/b&gt;&lt;/span&gt; &lt;span style="color: darkcyan;"&gt;%content_types&lt;/span&gt; = (&lt;br /&gt;&lt;span style="color: brown;"&gt;10 &lt;/span&gt;    &lt;span style="color: magenta;"&gt;RTF    &lt;/span&gt;=&amp;gt; &lt;span style="color: magenta;"&gt;"&lt;/span&gt;&lt;span style="color: magenta;"&gt;application/rtf&lt;/span&gt;&lt;span style="color: magenta;"&gt;"&lt;/span&gt;,&lt;br /&gt;&lt;span style="color: brown;"&gt;11 &lt;/span&gt;    &lt;span style="color: magenta;"&gt;LaTeX  &lt;/span&gt;=&amp;gt; &lt;span style="color: magenta;"&gt;"&lt;/span&gt;&lt;span style="color: magenta;"&gt;application/x-latex&lt;/span&gt;&lt;span style="color: magenta;"&gt;"&lt;/span&gt;,&lt;br /&gt;&lt;span style="color: brown;"&gt;12 &lt;/span&gt;    &lt;span style="color: magenta;"&gt;PDF    &lt;/span&gt;=&amp;gt; &lt;span style="color: magenta;"&gt;"&lt;/span&gt;&lt;span style="color: magenta;"&gt;application/pdf&lt;/span&gt;&lt;span style="color: magenta;"&gt;"&lt;/span&gt;,&lt;br /&gt;&lt;span style="color: brown;"&gt;13 &lt;/span&gt;);&lt;br /&gt;&lt;span style="color: brown;"&gt;14 &lt;/span&gt;&lt;span style="color: brown;"&gt;&lt;b&gt;my&lt;/b&gt;&lt;/span&gt; &lt;span style="color: darkcyan;"&gt;@wikis&lt;/span&gt;   = &lt;span style="color: magenta;"&gt;qw(&lt;/span&gt;&lt;span style="color: magenta;"&gt;Usemod Twiki Template Kwiki Confluence Moinmoin Tiddlywiki Mediawiki Textile&lt;/span&gt;&lt;span style="color: magenta;"&gt;)&lt;/span&gt;;&lt;br /&gt;&lt;span style="color: brown;"&gt;15 &lt;/span&gt;&lt;span style="color: brown;"&gt;&lt;b&gt;my&lt;/b&gt;&lt;/span&gt; &lt;span style="color: darkcyan;"&gt;%formats&lt;/span&gt; = (&lt;br /&gt;&lt;span style="color: brown;"&gt;16 &lt;/span&gt;    ( &lt;span style="color: brown;"&gt;&lt;b&gt;map&lt;/b&gt;&lt;/span&gt; { &lt;span style="color: darkcyan;"&gt;$_&lt;/span&gt; =&amp;gt; &lt;span style="color: magenta;"&gt;"&lt;/span&gt;&lt;span style="color: magenta;"&gt;Pod::Simple::&lt;/span&gt;&lt;span style="color: darkcyan;"&gt;$_&lt;/span&gt;&lt;span style="color: magenta;"&gt;"&lt;/span&gt; } &lt;span style="color: brown;"&gt;&lt;b&gt;keys&lt;/b&gt;&lt;/span&gt; &lt;span style="color: darkcyan;"&gt;%content_types&lt;/span&gt; ),&lt;br /&gt;&lt;span style="color: brown;"&gt;17 &lt;/span&gt;    ( &lt;span style="color: brown;"&gt;&lt;b&gt;map&lt;/b&gt;&lt;/span&gt; { &lt;span style="color: darkcyan;"&gt;$_&lt;/span&gt; =&amp;gt; &lt;span style="color: magenta;"&gt;"&lt;/span&gt;&lt;span style="color: magenta;"&gt;Pod::Simple::Wiki::&lt;/span&gt;&lt;span style="color: darkcyan;"&gt;$_&lt;/span&gt;&lt;span style="color: magenta;"&gt;"&lt;/span&gt; } &lt;span style="color: darkcyan;"&gt;@wikis&lt;/span&gt; )&lt;br /&gt;&lt;span style="color: brown;"&gt;18 &lt;/span&gt;);&lt;br /&gt;&lt;span style="color: brown;"&gt;19 &lt;/span&gt;&lt;br /&gt;&lt;span style="color: brown;"&gt;20 &lt;/span&gt;&lt;span style="color: brown;"&gt;&lt;b&gt;my&lt;/b&gt;&lt;/span&gt; &lt;span style="color: darkcyan;"&gt;$q&lt;/span&gt;        = &lt;span style="color: brown;"&gt;&lt;b&gt;new&lt;/b&gt;&lt;/span&gt; CGI;&lt;br /&gt;&lt;span style="color: brown;"&gt;21 &lt;/span&gt;&lt;span style="color: brown;"&gt;&lt;b&gt;my&lt;/b&gt;&lt;/span&gt; &lt;span style="color: darkcyan;"&gt;$filename&lt;/span&gt; = Pod::Simple::Search-&amp;gt;&lt;span style="color: brown;"&gt;&lt;b&gt;new&lt;/b&gt;&lt;/span&gt;-&amp;gt;inc(&lt;span style="color: magenta;"&gt;1&lt;/span&gt;)-&amp;gt;find( &lt;span style="color: darkcyan;"&gt;$q&lt;/span&gt;&lt;span style="color: darkcyan;"&gt;-&amp;gt;param&lt;/span&gt;(&lt;span style="color: magenta;"&gt;"&lt;/span&gt;&lt;span style="color: magenta;"&gt;pod&lt;/span&gt;&lt;span style="color: magenta;"&gt;"&lt;/span&gt;) );&lt;br /&gt;&lt;span style="color: brown;"&gt;22 &lt;/span&gt;&lt;span style="color: brown;"&gt;&lt;b&gt;my&lt;/b&gt;&lt;/span&gt; &lt;span style="color: darkcyan;"&gt;$format&lt;/span&gt;   = &lt;span style="color: darkcyan;"&gt;$q&lt;/span&gt;&lt;span style="color: darkcyan;"&gt;-&amp;gt;param&lt;/span&gt;(&lt;span style="color: magenta;"&gt;"&lt;/span&gt;&lt;span style="color: magenta;"&gt;format&lt;/span&gt;&lt;span style="color: magenta;"&gt;"&lt;/span&gt;) || &lt;span style="color: magenta;"&gt;"&lt;/span&gt;&lt;span style="color: magenta;"&gt;HTML&lt;/span&gt;&lt;span style="color: magenta;"&gt;"&lt;/span&gt;;&lt;br /&gt;&lt;span style="color: brown;"&gt;23 &lt;/span&gt;given (&lt;span style="color: darkcyan;"&gt;$format&lt;/span&gt;) {&lt;br /&gt;&lt;span style="color: brown;"&gt;24 &lt;/span&gt;    when (&lt;span style="color: magenta;"&gt;"&lt;/span&gt;&lt;span style="color: magenta;"&gt;source&lt;/span&gt;&lt;span style="color: magenta;"&gt;"&lt;/span&gt;) {&lt;br /&gt;&lt;span style="color: brown;"&gt;25 &lt;/span&gt;        &lt;span style="color: brown;"&gt;&lt;b&gt;print&lt;/b&gt;&lt;/span&gt; &lt;span style="color: darkcyan;"&gt;$q&lt;/span&gt;&lt;span style="color: darkcyan;"&gt;-&amp;gt;header&lt;/span&gt;(&lt;span style="color: magenta;"&gt;"&lt;/span&gt;&lt;span style="color: magenta;"&gt;text/plain&lt;/span&gt;&lt;span style="color: magenta;"&gt;"&lt;/span&gt;);&lt;br /&gt;&lt;span style="color: brown;"&gt;26 &lt;/span&gt;        &lt;span style="color: brown;"&gt;&lt;b&gt;open&lt;/b&gt;&lt;/span&gt; &lt;span style="color: darkcyan;"&gt;POD&lt;/span&gt;, &lt;span style="color: darkcyan;"&gt;$filename&lt;/span&gt;;&lt;br /&gt;&lt;span style="color: brown;"&gt;27 &lt;/span&gt;        &lt;span style="color: brown;"&gt;&lt;b&gt;print&lt;/b&gt;&lt;/span&gt; &lt;span style="color: darkcyan;"&gt;$_&lt;/span&gt; &lt;span style="color: brown;"&gt;&lt;b&gt;while&lt;/b&gt;&lt;/span&gt; (&lt;span style="color: darkcyan;"&gt;&amp;lt;POD&amp;gt;&lt;/span&gt;);&lt;br /&gt;&lt;span style="color: brown;"&gt;28 &lt;/span&gt;    }&lt;br /&gt;&lt;span style="color: brown;"&gt;29 &lt;/span&gt;    when (&lt;span style="color: magenta;"&gt;'&lt;/span&gt;&lt;span style="color: magenta;"&gt;HTML&lt;/span&gt;&lt;span style="color: magenta;"&gt;'&lt;/span&gt;) {&lt;br /&gt;&lt;span style="color: brown;"&gt;30 &lt;/span&gt;        &lt;span style="color: brown;"&gt;&lt;b&gt;my&lt;/b&gt;&lt;/span&gt; &lt;span style="color: darkcyan;"&gt;$parser&lt;/span&gt; = Pod::Simple::HTML-&amp;gt;&lt;span style="color: brown;"&gt;&lt;b&gt;new&lt;/b&gt;&lt;/span&gt;;&lt;br /&gt;&lt;span style="color: brown;"&gt;31 &lt;/span&gt;        &lt;span style="color: brown;"&gt;&lt;b&gt;print&lt;/b&gt;&lt;/span&gt; &lt;span style="color: darkcyan;"&gt;$q&lt;/span&gt;&lt;span style="color: darkcyan;"&gt;-&amp;gt;header&lt;/span&gt;(&lt;span style="color: magenta;"&gt;"&lt;/span&gt;&lt;span style="color: magenta;"&gt;text/html&lt;/span&gt;&lt;span style="color: magenta;"&gt;"&lt;/span&gt;);&lt;br /&gt;&lt;span style="color: brown;"&gt;32 &lt;/span&gt;        &lt;span style="color: darkcyan;"&gt;$parser&lt;/span&gt;&lt;span style="color: darkcyan;"&gt;-&amp;gt;perldoc_url_prefix&lt;/span&gt;( &lt;span style="color: darkcyan;"&gt;$q&lt;/span&gt;&lt;span style="color: darkcyan;"&gt;-&amp;gt;url&lt;/span&gt;( -&lt;span style="color: magenta;"&gt;path_info &lt;/span&gt;=&amp;gt; &lt;span style="color: magenta;"&gt;1&lt;/span&gt; ) . &lt;span style="color: magenta;"&gt;"&lt;/span&gt;&lt;span style="color: magenta;"&gt;?pod=&lt;/span&gt;&lt;span style="color: magenta;"&gt;"&lt;/span&gt; );&lt;br /&gt;&lt;span style="color: brown;"&gt;33 &lt;/span&gt;        &lt;span style="color: brown;"&gt;&lt;b&gt;my&lt;/b&gt;&lt;/span&gt; &lt;span style="color: darkcyan;"&gt;$footer&lt;/span&gt; = &lt;span style="color: magenta;"&gt;"&lt;/span&gt;&lt;span style="color: magenta;"&gt;&amp;lt;hr&amp;gt;&lt;/span&gt;&lt;span style="color: magenta;"&gt;"&lt;/span&gt;&lt;br /&gt;&lt;span style="color: brown;"&gt;34 &lt;/span&gt;            . &lt;span style="color: brown;"&gt;&lt;b&gt;join&lt;/b&gt;&lt;/span&gt;( &lt;span style="color: magenta;"&gt;"&lt;/span&gt;&lt;span style="color: magenta;"&gt; &lt;/span&gt;&lt;span style="color: magenta;"&gt;"&lt;/span&gt;, &lt;span style="color: brown;"&gt;&lt;b&gt;map&lt;/b&gt;&lt;/span&gt; { make_link(&lt;span style="color: darkcyan;"&gt;$_&lt;/span&gt;) } &lt;span style="color: magenta;"&gt;"&lt;/span&gt;&lt;span style="color: magenta;"&gt;source&lt;/span&gt;&lt;span style="color: magenta;"&gt;"&lt;/span&gt;, &lt;span style="color: brown;"&gt;&lt;b&gt;keys&lt;/b&gt;&lt;/span&gt; &lt;span style="color: darkcyan;"&gt;%content_types&lt;/span&gt; )&lt;br /&gt;&lt;span style="color: brown;"&gt;35 &lt;/span&gt;            . &lt;span style="color: magenta;"&gt;"&lt;/span&gt;&lt;span style="color: magenta;"&gt; | Wiki formats: &lt;/span&gt;&lt;span style="color: magenta;"&gt;"&lt;/span&gt;&lt;br /&gt;&lt;span style="color: brown;"&gt;36 &lt;/span&gt;            . &lt;span style="color: brown;"&gt;&lt;b&gt;join&lt;/b&gt;&lt;/span&gt;( &lt;span style="color: magenta;"&gt;"&lt;/span&gt;&lt;span style="color: magenta;"&gt; &lt;/span&gt;&lt;span style="color: magenta;"&gt;"&lt;/span&gt;, &lt;span style="color: brown;"&gt;&lt;b&gt;map&lt;/b&gt;&lt;/span&gt; { make_link(&lt;span style="color: darkcyan;"&gt;$_&lt;/span&gt;) } &lt;span style="color: darkcyan;"&gt;@wikis&lt;/span&gt; );&lt;br /&gt;&lt;span style="color: brown;"&gt;37 &lt;/span&gt;        &lt;span style="color: darkcyan;"&gt;$parser&lt;/span&gt;&lt;span style="color: darkcyan;"&gt;-&amp;gt;html_footer&lt;/span&gt;(qq[\n&amp;lt;!-- end doc --&amp;gt;\n\n&lt;span style="color: darkcyan;"&gt;$footer&lt;/span&gt;&amp;lt;/body&amp;gt;&amp;lt;/html&amp;gt;\n]);&lt;br /&gt;&lt;span style="color: brown;"&gt;38 &lt;/span&gt;        &lt;span style="color: darkcyan;"&gt;$parser&lt;/span&gt;&lt;span style="color: darkcyan;"&gt;-&amp;gt;output_fh&lt;/span&gt;(*STDOUT);&lt;br /&gt;&lt;span style="color: brown;"&gt;39 &lt;/span&gt;        &lt;span style="color: darkcyan;"&gt;$parser&lt;/span&gt;&lt;span style="color: darkcyan;"&gt;-&amp;gt;parse_file&lt;/span&gt;(&lt;span style="color: darkcyan;"&gt;$filename&lt;/span&gt;);&lt;br /&gt;&lt;span style="color: brown;"&gt;40 &lt;/span&gt;    }&lt;br /&gt;&lt;span style="color: brown;"&gt;41 &lt;/span&gt;    when (&lt;span style="color: darkcyan;"&gt;%formats&lt;/span&gt;) {&lt;br /&gt;&lt;span style="color: brown;"&gt;42 &lt;/span&gt;        &lt;span style="color: brown;"&gt;&lt;b&gt;my&lt;/b&gt;&lt;/span&gt; &lt;span style="color: darkcyan;"&gt;$class&lt;/span&gt; = &lt;span style="color: darkcyan;"&gt;$formats{$format}&lt;/span&gt;;&lt;br /&gt;&lt;span style="color: brown;"&gt;43 &lt;/span&gt;        &lt;span style="color: brown;"&gt;&lt;b&gt;eval&lt;/b&gt;&lt;/span&gt; &lt;span style="color: magenta;"&gt;"&lt;/span&gt;&lt;span style="color: magenta;"&gt;require &lt;/span&gt;&lt;span style="color: darkcyan;"&gt;$class&lt;/span&gt;&lt;span style="color: magenta;"&gt;"&lt;/span&gt;;&lt;br /&gt;&lt;span style="color: brown;"&gt;44 &lt;/span&gt;        &lt;span style="color: brown;"&gt;&lt;b&gt;print&lt;/b&gt;&lt;/span&gt; &lt;span style="color: darkcyan;"&gt;$q&lt;/span&gt;&lt;span style="color: darkcyan;"&gt;-&amp;gt;header&lt;/span&gt;( &lt;span style="color: darkcyan;"&gt;$content_types{$format}&lt;/span&gt; || &lt;span style="color: magenta;"&gt;"&lt;/span&gt;&lt;span style="color: magenta;"&gt;text/plain&lt;/span&gt;&lt;span style="color: magenta;"&gt;"&lt;/span&gt; );&lt;br /&gt;&lt;span style="color: brown;"&gt;45 &lt;/span&gt;        &lt;span style="color: darkcyan;"&gt;$class&lt;/span&gt;&lt;span style="color: darkcyan;"&gt;-&amp;gt;filter&lt;/span&gt;(&lt;span style="color: darkcyan;"&gt;$filename&lt;/span&gt;);&lt;br /&gt;&lt;span style="color: brown;"&gt;46 &lt;/span&gt;    }&lt;br /&gt;&lt;span style="color: brown;"&gt;47 &lt;/span&gt;    default {&lt;br /&gt;&lt;span style="color: brown;"&gt;48 &lt;/span&gt;        &lt;span style="color: brown;"&gt;&lt;b&gt;die&lt;/b&gt;&lt;/span&gt;(&lt;span style="color: magenta;"&gt;"&lt;/span&gt;&lt;span style="color: magenta;"&gt;Formato desconocido '&lt;/span&gt;&lt;span style="color: darkcyan;"&gt;$format&lt;/span&gt;&lt;span style="color: magenta;"&gt;'&lt;/span&gt;&lt;span style="color: magenta;"&gt;"&lt;/span&gt;);&lt;br /&gt;&lt;span style="color: brown;"&gt;49 &lt;/span&gt;    }&lt;br /&gt;&lt;span style="color: brown;"&gt;50 &lt;/span&gt;}&lt;br /&gt;&lt;span style="color: brown;"&gt;51 &lt;/span&gt;&lt;br /&gt;&lt;span style="color: brown;"&gt;52 &lt;/span&gt;&lt;span style="color: brown;"&gt;&lt;b&gt;sub&lt;/b&gt;&lt;/span&gt;&lt;span style="color: darkcyan;"&gt; &lt;/span&gt;&lt;span style="color: darkcyan;"&gt;make_link &lt;/span&gt;{&lt;br /&gt;&lt;span style="color: brown;"&gt;53 &lt;/span&gt;    &lt;span style="color: brown;"&gt;&lt;b&gt;my&lt;/b&gt;&lt;/span&gt; &lt;span style="color: darkcyan;"&gt;$fmt&lt;/span&gt; = &lt;span style="color: brown;"&gt;&lt;b&gt;shift&lt;/b&gt;&lt;/span&gt;;&lt;br /&gt;&lt;span style="color: brown;"&gt;54 &lt;/span&gt;    &lt;span style="color: darkcyan;"&gt;$q&lt;/span&gt;&lt;span style="color: darkcyan;"&gt;-&amp;gt;a&lt;/span&gt;( { &lt;span style="color: magenta;"&gt;href &lt;/span&gt;=&amp;gt; &lt;span style="color: darkcyan;"&gt;$q&lt;/span&gt;&lt;span style="color: darkcyan;"&gt;-&amp;gt;url&lt;/span&gt;( -&lt;span style="color: magenta;"&gt;path_info &lt;/span&gt;=&amp;gt; &lt;span style="color: magenta;"&gt;1&lt;/span&gt;, -&lt;span style="color: magenta;"&gt;query &lt;/span&gt;=&amp;gt; &lt;span style="color: magenta;"&gt;1&lt;/span&gt; ) . &lt;span style="color: magenta;"&gt;"&lt;/span&gt;&lt;span style="color: slateblue;"&gt;\&amp;amp;&lt;/span&gt;&lt;span style="color: magenta;"&gt;format=&lt;/span&gt;&lt;span style="color: darkcyan;"&gt;$fmt&lt;/span&gt;&lt;span style="color: magenta;"&gt;"&lt;/span&gt; }, &lt;span style="color: darkcyan;"&gt;$fmt&lt;/span&gt; );&lt;br /&gt;&lt;span style="color: brown;"&gt;55 &lt;/span&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5238463735728501931-2896200630160876143?l=perliscopio.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://perliscopio.blogspot.com/feeds/2896200630160876143/comments/default' title='Enviar comentarios'/><link rel='replies' type='text/html' href='http://perliscopio.blogspot.com/2009/11/procesando-pod-con-podsimple.html#comment-form' title='0 comentarios'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5238463735728501931/posts/default/2896200630160876143'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5238463735728501931/posts/default/2896200630160876143'/><link rel='alternate' type='text/html' href='http://perliscopio.blogspot.com/2009/11/procesando-pod-con-podsimple.html' title='Procesando POD con Pod::Simple'/><author><name>Jose Rey</name><uri>http://www.blogger.com/profile/15071755167581242815</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5238463735728501931.post-6842903451613832693</id><published>2009-11-15T18:47:00.004-04:30</published><updated>2009-11-15T19:41:30.116-04:30</updated><category scheme='http://www.blogger.com/atom/ns#' term='Perl'/><category scheme='http://www.blogger.com/atom/ns#' term='CPAN'/><title type='text'>Herramientas de documentación en Perl</title><content type='html'>[&lt;a href="http://perliscope.blogspot.com/2009/11/perl-documetantion-tools.html"&gt;English translation&lt;/a&gt;]&lt;br /&gt;Perl tiene su propio formato de documentación llamado POD (del inglés Plain Old Documentation), este formato es estructurado y fué específicamente diseñado para ser manipulado fácilmente. POD se usa no solo como herramienta para la documentar Perl, sino como lenguaje de Wiki y hasta para escribir libros.&lt;br /&gt;&lt;br /&gt;En perl la herramienta más conocida para leer la documentación es &lt;a href="http://perldoc.perl.org/perldoc.html"&gt;perldoc&lt;/a&gt;, que funciona de manera muy similar al manual de unix&amp;nbsp;&lt;a href="http://linux.die.net/man/1/man"&gt;man&lt;/a&gt;(1), así cuando queremos ver la documentación de un módulo podemos hacer:&lt;br /&gt;&lt;br /&gt;$ perldoc IO::Handle&lt;br /&gt;&lt;br /&gt;Lo que nos mostrará el manual de IO::Handle, también podemos obtener el manual del módulo en otra variedad de formatos, por ejemplo, lo podemos guardar en formato "man", HTML o incluso LaTeX:&lt;br /&gt;&lt;br /&gt;$ perldoc -T -o LaTeX IO::Handle &amp;gt; IO::Handle.tex&lt;br /&gt;$ perldoc -T -o html IO::Handle &amp;gt; IO::Handle.html&lt;br /&gt;&lt;br /&gt;Si vemos el HTML generado nos daremos cuenta que los enlaces generados al resto de la documentación se refieren al CPAN, pero esto es solo la forma en la que funciona perldoc, existen &lt;a href="http://search.cpan.org/search?query=pod"&gt;cientos de módulos para procesar POD&lt;/a&gt;, que permiten manipulaciones avanzadas y convertirlo a HTML, XML, LaTeX, texto y DocBook, entre otros.&lt;br /&gt;&lt;br /&gt;Cuando se necesita mas control sobre la generación de los documentos, puedes usar otras herramientas como: pod2html y pod2latex que permiten crear documentos basados en varios archivos POD que se procesan en conjunto, por ejemplo para hacer un libro, donde cada capítulo se guarda en un POD diferente.&lt;br /&gt;&lt;br /&gt;Si necesitas control total sobre la conversión de POD, siempre puedes programar utilizando los módulos disponibles en el CPAN, y uno de los más fáciles de usar es Pod::Simple, que ofrece varias conversiones predefinidas, por ejemplo si quieres generar HTML en una aplicación CGI, puedes hacerlo con facilidad:&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;span style="color: brown;"&gt;1 &lt;/span&gt;&lt;span style="color: #a020f0;"&gt;use &lt;/span&gt;CGI;&lt;br /&gt;&lt;span style="color: brown;"&gt;2 &lt;/span&gt;&lt;span style="color: #a020f0;"&gt;use &lt;/span&gt;Pod::Simple::HTML;&lt;br /&gt;&lt;span style="color: brown;"&gt;3 &lt;/span&gt;&lt;br /&gt;&lt;span style="color: brown;"&gt;4 &lt;/span&gt;&lt;span style="color: brown;"&gt;&lt;b&gt;my&lt;/b&gt;&lt;/span&gt; &lt;span style="color: darkcyan;"&gt;$q&lt;/span&gt; = &lt;span style="color: brown;"&gt;&lt;b&gt;new&lt;/b&gt;&lt;/span&gt; CGI;&lt;br /&gt;&lt;span style="color: brown;"&gt;5 &lt;/span&gt;&lt;span style="color: brown;"&gt;&lt;b&gt;my&lt;/b&gt;&lt;/span&gt; &lt;span style="color: darkcyan;"&gt;$parser&lt;/span&gt; = Pod::Simple::HTML-&amp;gt;&lt;span style="color: brown;"&gt;&lt;b&gt;new&lt;/b&gt;&lt;/span&gt;;&lt;br /&gt;&lt;span style="color: brown;"&gt;6 &lt;/span&gt;&lt;span style="color: darkcyan;"&gt;$parser&lt;/span&gt;&lt;span style="color: darkcyan;"&gt;-&amp;gt;output_fh&lt;/span&gt;(*STDOUT);&lt;br /&gt;&lt;span style="color: brown;"&gt;7 &lt;/span&gt;&lt;br /&gt;&lt;span style="color: brown;"&gt;8 &lt;/span&gt;&lt;span style="color: brown;"&gt;&lt;b&gt;print&lt;/b&gt;&lt;/span&gt; &lt;span style="color: darkcyan;"&gt;$q&lt;/span&gt;&lt;span style="color: darkcyan;"&gt;-&amp;gt;header&lt;/span&gt;(&lt;span style="color: magenta;"&gt;"&lt;/span&gt;&lt;span style="color: magenta;"&gt;text/html&lt;/span&gt;&lt;span style="color: magenta;"&gt;"&lt;/span&gt;);&lt;br /&gt;&lt;span style="color: brown;"&gt;9 &lt;/span&gt;&lt;span style="color: darkcyan;"&gt;$parser&lt;/span&gt;&lt;span style="color: darkcyan;"&gt;-&amp;gt;parse_file&lt;/span&gt;(&lt;span style="color: magenta;"&gt;"&lt;/span&gt;&lt;span style="color: magenta;"&gt;/usr/share/perl/5.8/IO/File.pod&lt;/span&gt;&lt;span style="color: magenta;"&gt;"&lt;/span&gt;);&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;Este programa inicializa los objetos CGI y Pod::Simple::HTML (líneas 4 a 6), envía los encabezados de HTTP (línea 6) y finalmente envía el documento en HTML (línea 9).&lt;br /&gt;&lt;br /&gt;En este caso debes conocer el nombre exacto del POD que deseas enviar, sin embargo si quieres saber el nombre de un archivo que contiene información sobre un módulo en particular, debes buscarlo, ¿donde?, pues lo más recomendable es buscarlo en los mismos sitios donde perl buscará los módulos y los ejecutables.&lt;br /&gt;&lt;br /&gt;La variable @INC contiene los lugares donde perl busca los módulos que usamos en nuestros programas, esta es una combinación de lugares predefinidos al momento de compilar perl , el contenido de la variable de ambiente PERL5LIB y los lugares epecificados con "use lib" en el código de programas y módulos. Por otra parte cuando perl debe ejecutar un programa lo busca en la variable de ambiente PATH, así que para encontrar el archivo que contiene el POD de un módulo o programa en Perl&amp;nbsp; podemos usar una función como find_pod que se muestra a continuación:&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;span style="color: brown;"&gt; 1 &lt;/span&gt;&lt;span style="color: #a020f0;"&gt;use &lt;/span&gt;Modern::Perl;&lt;br /&gt;&lt;span style="color: brown;"&gt; 2 &lt;/span&gt;&lt;span style="color: #a020f0;"&gt;use &lt;/span&gt;Env::Path;&lt;br /&gt;&lt;span style="color: brown;"&gt; 3 &lt;/span&gt;&lt;span style="color: #a020f0;"&gt;use &lt;/span&gt;File::Spec::Functions;&lt;br /&gt;&lt;span style="color: brown;"&gt; 4 &lt;/span&gt;&lt;br /&gt;&lt;span style="color: brown;"&gt; 5 &lt;/span&gt;&lt;span style="color: brown;"&gt;&lt;b&gt;sub&lt;/b&gt;&lt;/span&gt;&lt;span style="color: darkcyan;"&gt; &lt;/span&gt;&lt;span style="color: darkcyan;"&gt;find_pod&lt;/span&gt;&lt;br /&gt;&lt;span style="color: brown;"&gt; 6 &lt;/span&gt;{&lt;br /&gt;&lt;span style="color: brown;"&gt; 7 &lt;/span&gt;    &lt;span style="color: brown;"&gt;&lt;b&gt;my&lt;/b&gt;&lt;/span&gt; &lt;span style="color: darkcyan;"&gt;$module&lt;/span&gt; = &lt;span style="color: brown;"&gt;&lt;b&gt;shift&lt;/b&gt;&lt;/span&gt;;&lt;br /&gt;&lt;span style="color: brown;"&gt; 8 &lt;/span&gt;    &lt;span style="color: brown;"&gt;&lt;b&gt;my&lt;/b&gt;&lt;/span&gt; &lt;span style="color: darkcyan;"&gt;@module_path&lt;/span&gt; = &lt;span style="color: brown;"&gt;&lt;b&gt;split&lt;/b&gt;&lt;/span&gt;(&lt;span style="color: magenta;"&gt;"&lt;/span&gt;&lt;span style="color: magenta;"&gt;::&lt;/span&gt;&lt;span style="color: magenta;"&gt;"&lt;/span&gt;, &lt;span style="color: darkcyan;"&gt;$module&lt;/span&gt;);&lt;br /&gt;&lt;span style="color: brown;"&gt; 9 &lt;/span&gt;    &lt;span style="color: brown;"&gt;&lt;b&gt;for&lt;/b&gt;&lt;/span&gt; &lt;span style="color: brown;"&gt;&lt;b&gt;my&lt;/b&gt;&lt;/span&gt; &lt;span style="color: darkcyan;"&gt;$dir&lt;/span&gt; ( &lt;span style="color: darkcyan;"&gt;@INC&lt;/span&gt;, Env::Path-&amp;gt;PATH-&amp;gt;List ) {&lt;br /&gt;&lt;span style="color: brown;"&gt;10 &lt;/span&gt;        &lt;span style="color: brown;"&gt;&lt;b&gt;for&lt;/b&gt;&lt;/span&gt; &lt;span style="color: brown;"&gt;&lt;b&gt;my&lt;/b&gt;&lt;/span&gt; &lt;span style="color: darkcyan;"&gt;$ext&lt;/span&gt; ( &lt;span style="color: magenta;"&gt;''&lt;/span&gt;, &lt;span style="color: magenta;"&gt;'&lt;/span&gt;&lt;span style="color: magenta;"&gt;.pod&lt;/span&gt;&lt;span style="color: magenta;"&gt;'&lt;/span&gt;, &lt;span style="color: magenta;"&gt;'&lt;/span&gt;&lt;span style="color: magenta;"&gt;.pm&lt;/span&gt;&lt;span style="color: magenta;"&gt;'&lt;/span&gt;, &lt;span style="color: magenta;"&gt;'&lt;/span&gt;&lt;span style="color: magenta;"&gt;.pl&lt;/span&gt;&lt;span style="color: magenta;"&gt;'&lt;/span&gt; ) {&lt;br /&gt;&lt;span style="color: brown;"&gt;11 &lt;/span&gt;            &lt;span style="color: brown;"&gt;&lt;b&gt;my&lt;/b&gt;&lt;/span&gt; &lt;span style="color: darkcyan;"&gt;$name&lt;/span&gt; = catfile(&lt;span style="color: darkcyan;"&gt;$dir&lt;/span&gt;, &lt;span style="color: darkcyan;"&gt;@module_path&lt;/span&gt;) . &lt;span style="color: darkcyan;"&gt;$ext&lt;/span&gt;;&lt;br /&gt;&lt;span style="color: brown;"&gt;12 &lt;/span&gt;            &lt;span style="color: brown;"&gt;&lt;b&gt;return&lt;/b&gt;&lt;/span&gt; &lt;span style="color: darkcyan;"&gt;$name&lt;/span&gt; &lt;span style="color: brown;"&gt;&lt;b&gt;if&lt;/b&gt;&lt;/span&gt; &lt;span style="color: brown;"&gt;&lt;b&gt;-e&lt;/b&gt;&lt;/span&gt; &lt;span style="color: darkcyan;"&gt;$name&lt;/span&gt;;&lt;br /&gt;&lt;span style="color: brown;"&gt;13 &lt;/span&gt;        }&lt;br /&gt;&lt;span style="color: brown;"&gt;14 &lt;/span&gt;    }&lt;br /&gt;&lt;span style="color: brown;"&gt;15 &lt;/span&gt;    &lt;span style="color: brown;"&gt;&lt;b&gt;return&lt;/b&gt;&lt;/span&gt; &lt;span style="color: brown;"&gt;&lt;b&gt;undef&lt;/b&gt;&lt;/span&gt;;&lt;br /&gt;&lt;span style="color: brown;"&gt;16 &lt;/span&gt;}&lt;br /&gt;&lt;span style="color: brown;"&gt;17 &lt;/span&gt;&lt;br /&gt;&lt;span style="color: brown;"&gt;18 &lt;/span&gt;&lt;span style="color: brown;"&gt;&lt;b&gt;print&lt;/b&gt;&lt;/span&gt; &lt;span style="color: magenta;"&gt;"&lt;/span&gt;&lt;span style="color: magenta;"&gt;Nombre: &lt;/span&gt;&lt;span style="color: magenta;"&gt;"&lt;/span&gt;, find_pod(&lt;span style="color: darkcyan;"&gt;@ARGV&lt;/span&gt;), &lt;span style="color: magenta;"&gt;"&lt;/span&gt;&lt;span style="color: slateblue;"&gt;\n&lt;/span&gt;&lt;span style="color: magenta;"&gt;"&lt;/span&gt;;&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;Esta función recibe el nombre del módulo o programa, y lo separa por "::", luego itera todos los directorios que se encuentran en @INC y el PATH del sistema que convertimos en una lista con "&lt;code&gt;Env::Path-&amp;gt;PATH-&amp;gt;List&lt;/code&gt;" en la línea 9, para cada directorio se buscan los nombres y los nombres aumentados con las extensiones: pod, pm y pl, el primer nombre encontrado es retornado, y si no se consigue nada se retorna undef.&lt;br /&gt;&lt;br /&gt;Nótese el uso de "&lt;code&gt;Env::Path&lt;/code&gt;" para obtener el path del sistema de manera portable y "&lt;code&gt;File::Spec::Functions&lt;/code&gt;" que importa la función "&lt;code&gt;catfile&lt;/code&gt;" para generar los nombres de archivo permite concatenar un nombre de archivo de manera portable, haciendo que esta subrutina funcione en unix y windows.&lt;br /&gt;&lt;br /&gt;Sin embargo, hice esto solo por diversión, porque en CPAN ya hay algo mucho mejor: "&lt;code&gt;Pod::Simple::Search&lt;/code&gt;", que está bien hecha, se puede instalar en cualquier lado y es mucho más flexible que la subrutina de juguete del ejemplo anterior, así que nuestro CGI para mostrar documentación en POD queda así:&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;span style="color: brown;"&gt; 1 &lt;/span&gt;&lt;span style="color: #a020f0;"&gt;#!/usr/bin/perl&lt;/span&gt;&lt;br /&gt;&lt;span style="color: brown;"&gt; 2 &lt;/span&gt;&lt;span style="color: #a020f0;"&gt;use &lt;/span&gt;CGI;&lt;br /&gt;&lt;span style="color: brown;"&gt; 3 &lt;/span&gt;&lt;span style="color: #a020f0;"&gt;use &lt;/span&gt;Pod::Simple::HTML;&lt;br /&gt;&lt;span style="color: brown;"&gt; 4 &lt;/span&gt;&lt;span style="color: #a020f0;"&gt;use &lt;/span&gt;Pod::Simple::Search;&lt;br /&gt;&lt;span style="color: brown;"&gt; 5 &lt;/span&gt;&lt;br /&gt;&lt;span style="color: brown;"&gt; 6 &lt;/span&gt;&lt;span style="color: brown;"&gt;&lt;b&gt;my&lt;/b&gt;&lt;/span&gt; &lt;span style="color: darkcyan;"&gt;$q&lt;/span&gt; = &lt;span style="color: brown;"&gt;&lt;b&gt;new&lt;/b&gt;&lt;/span&gt; CGI;&lt;br /&gt;&lt;span style="color: brown;"&gt; 7 &lt;/span&gt;&lt;span style="color: brown;"&gt;&lt;b&gt;my&lt;/b&gt;&lt;/span&gt; &lt;span style="color: darkcyan;"&gt;$parser&lt;/span&gt; = Pod::Simple::HTML-&amp;gt;&lt;span style="color: brown;"&gt;&lt;b&gt;new&lt;/b&gt;&lt;/span&gt;;&lt;br /&gt;&lt;span style="color: brown;"&gt; 8 &lt;/span&gt;&lt;span style="color: darkcyan;"&gt;$parser&lt;/span&gt;&lt;span style="color: darkcyan;"&gt;-&amp;gt;output_fh&lt;/span&gt;(*STDOUT);&lt;br /&gt;&lt;span style="color: brown;"&gt; 9 &lt;/span&gt;&lt;br /&gt;&lt;span style="color: brown;"&gt;10 &lt;/span&gt;&lt;span style="color: brown;"&gt;&lt;b&gt;my&lt;/b&gt;&lt;/span&gt; &lt;span style="color: darkcyan;"&gt;$filename&lt;/span&gt; = Pod::Simple::Search-&amp;gt;&lt;span style="color: brown;"&gt;&lt;b&gt;new&lt;/b&gt;&lt;/span&gt;-&amp;gt;inc(&lt;span style="color: magenta;"&gt;1&lt;/span&gt;)-&amp;gt;find(&lt;span style="color: darkcyan;"&gt;$q&lt;/span&gt;&lt;span style="color: darkcyan;"&gt;-&amp;gt;param&lt;/span&gt;(&lt;span style="color: magenta;"&gt;"&lt;/span&gt;&lt;span style="color: magenta;"&gt;pod&lt;/span&gt;&lt;span style="color: magenta;"&gt;"&lt;/span&gt;));&lt;br /&gt;&lt;span style="color: brown;"&gt;11 &lt;/span&gt;&lt;span style="color: brown;"&gt;&lt;b&gt;print&lt;/b&gt;&lt;/span&gt; &lt;span style="color: darkcyan;"&gt;$q&lt;/span&gt;&lt;span style="color: darkcyan;"&gt;-&amp;gt;header&lt;/span&gt;(&lt;span style="color: magenta;"&gt;"&lt;/span&gt;&lt;span style="color: magenta;"&gt;text/html&lt;/span&gt;&lt;span style="color: magenta;"&gt;"&lt;/span&gt;);&lt;br /&gt;&lt;span style="color: brown;"&gt;12 &lt;/span&gt;&lt;span style="color: darkcyan;"&gt;$parser&lt;/span&gt;&lt;span style="color: darkcyan;"&gt;-&amp;gt;parse_file&lt;/span&gt;(&lt;span style="color: darkcyan;"&gt;$filename&lt;/span&gt;);&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;Si tenemos un servidor web configurado, solamente copiamos el programa en el directorio apropiado para ejecutar CGI con el nombre perldocweb, lo marcamos como ejecutable, y todo debería funcionar, para probarlo podemos visitar:&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;http://localhost/cgi-bin/perldocweb?pod=IO::File&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;lo que muestra el manual de IO::File en el navegador, aunque todavía los enlaces apuntan al CPAN, si quieres que los enlaces apunten al mismo servidor de documentación hay que establecer el prefijo para generar los enlaces (&lt;code&gt;perldoc_url_prefix&lt;/code&gt;), para ello utilizaré el método url() de CGI, que usado como se muestra en la línea 12 retorna el URL completo del script sin el query:&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;span style="color: brown;"&gt; 1 &lt;/span&gt;&lt;span style="color: #a020f0;"&gt;#!/usr/bin/perl&lt;/span&gt;&lt;br /&gt;&lt;span style="color: brown;"&gt; 2 &lt;/span&gt;&lt;span style="color: #a020f0;"&gt;use &lt;/span&gt;CGI;&lt;br /&gt;&lt;span style="color: brown;"&gt; 3 &lt;/span&gt;&lt;span style="color: #a020f0;"&gt;use &lt;/span&gt;Pod::Simple::HTML;&lt;br /&gt;&lt;span style="color: brown;"&gt; 4 &lt;/span&gt;&lt;span style="color: #a020f0;"&gt;use &lt;/span&gt;Pod::Simple::Search;&lt;br /&gt;&lt;span style="color: brown;"&gt; 5 &lt;/span&gt;&lt;br /&gt;&lt;span style="color: brown;"&gt; 6 &lt;/span&gt;&lt;span style="color: brown;"&gt;&lt;b&gt;my&lt;/b&gt;&lt;/span&gt; &lt;span style="color: darkcyan;"&gt;$q&lt;/span&gt; = &lt;span style="color: brown;"&gt;&lt;b&gt;new&lt;/b&gt;&lt;/span&gt; CGI;&lt;br /&gt;&lt;span style="color: brown;"&gt; 7 &lt;/span&gt;&lt;span style="color: brown;"&gt;&lt;b&gt;my&lt;/b&gt;&lt;/span&gt; &lt;span style="color: darkcyan;"&gt;$parser&lt;/span&gt; = Pod::Simple::HTML-&amp;gt;&lt;span style="color: brown;"&gt;&lt;b&gt;new&lt;/b&gt;&lt;/span&gt;;&lt;br /&gt;&lt;span style="color: brown;"&gt; 8 &lt;/span&gt;&lt;span style="color: darkcyan;"&gt;$parser&lt;/span&gt;&lt;span style="color: darkcyan;"&gt;-&amp;gt;output_fh&lt;/span&gt;(*STDOUT);&lt;br /&gt;&lt;span style="color: brown;"&gt; 9 &lt;/span&gt;&lt;br /&gt;&lt;span style="color: brown;"&gt;10 &lt;/span&gt;&lt;span style="color: brown;"&gt;&lt;b&gt;my&lt;/b&gt;&lt;/span&gt; &lt;span style="color: darkcyan;"&gt;$filename&lt;/span&gt; = Pod::Simple::Search-&amp;gt;&lt;span style="color: brown;"&gt;&lt;b&gt;new&lt;/b&gt;&lt;/span&gt;-&amp;gt;inc(&lt;span style="color: magenta;"&gt;1&lt;/span&gt;)-&amp;gt;find(&lt;span style="color: darkcyan;"&gt;$q&lt;/span&gt;&lt;span style="color: darkcyan;"&gt;-&amp;gt;param&lt;/span&gt;(&lt;span style="color: magenta;"&gt;"&lt;/span&gt;&lt;span style="color: magenta;"&gt;pod&lt;/span&gt;&lt;span style="color: magenta;"&gt;"&lt;/span&gt;));&lt;br /&gt;&lt;span style="color: brown;"&gt;11 &lt;/span&gt;&lt;span style="color: brown;"&gt;&lt;b&gt;print&lt;/b&gt;&lt;/span&gt; &lt;span style="color: darkcyan;"&gt;$q&lt;/span&gt;&lt;span style="color: darkcyan;"&gt;-&amp;gt;header&lt;/span&gt;(&lt;span style="color: magenta;"&gt;"&lt;/span&gt;&lt;span style="color: magenta;"&gt;text/html&lt;/span&gt;&lt;span style="color: magenta;"&gt;"&lt;/span&gt;);&lt;br /&gt;&lt;span style="color: brown;"&gt;12 &lt;/span&gt;&lt;span style="color: darkcyan;"&gt;$parser&lt;/span&gt;&lt;span style="color: darkcyan;"&gt;-&amp;gt;perldoc_url_prefix&lt;/span&gt;(&lt;span style="color: darkcyan;"&gt;$q&lt;/span&gt;&lt;span style="color: darkcyan;"&gt;-&amp;gt;url&lt;/span&gt;(-&lt;span style="color: magenta;"&gt;path_info&lt;/span&gt;=&amp;gt;&lt;span style="color: magenta;"&gt;1&lt;/span&gt;) . &lt;span style="color: magenta;"&gt;"&lt;/span&gt;&lt;span style="color: magenta;"&gt;?pod=&lt;/span&gt;&lt;span style="color: magenta;"&gt;"&lt;/span&gt;);&lt;br /&gt;&lt;span style="color: brown;"&gt;13 &lt;/span&gt;&lt;span style="color: darkcyan;"&gt;$parser&lt;/span&gt;&lt;span style="color: darkcyan;"&gt;-&amp;gt;parse_file&lt;/span&gt;(&lt;span style="color: darkcyan;"&gt;$filename&lt;/span&gt;);&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;Nada mal, un servidor de documentación sencillo en 13 líneas, en el próximo artículo veremos como convertir POD a otra cantidad de formatos, mientras tanto pueden instalar &lt;a href="http://search.cpan.org/perldoc?Pod::Server"&gt;Pod::Server&lt;/a&gt; y ver como se hace esto con mucha más elegancia.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5238463735728501931-6842903451613832693?l=perliscopio.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://perliscopio.blogspot.com/feeds/6842903451613832693/comments/default' title='Enviar comentarios'/><link rel='replies' type='text/html' href='http://perliscopio.blogspot.com/2009/11/herramientas-de-documentacion-en-perl.html#comment-form' title='0 comentarios'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5238463735728501931/posts/default/6842903451613832693'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5238463735728501931/posts/default/6842903451613832693'/><link rel='alternate' type='text/html' href='http://perliscopio.blogspot.com/2009/11/herramientas-de-documentacion-en-perl.html' title='Herramientas de documentación en Perl'/><author><name>Jose Rey</name><uri>http://www.blogger.com/profile/15071755167581242815</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5238463735728501931.post-3861835314264816460</id><published>2009-11-04T23:55:00.004-04:30</published><updated>2009-11-06T11:01:49.492-04:30</updated><category scheme='http://www.blogger.com/atom/ns#' term='Tutorial'/><category scheme='http://www.blogger.com/atom/ns#' term='Perl'/><category scheme='http://www.blogger.com/atom/ns#' term='Programación'/><title type='text'>Manejando errores en Perl</title><content type='html'>[&lt;a href="http://perliscope.blogspot.com/2009/11/perl-error-handling.html"&gt;English Translation&lt;/a&gt;]&lt;br /&gt;&lt;br /&gt;En Perl el manejo de excepciones es un poco diferente al que probablemente estamos acostumbrados, en particular Perl no tiene try/catch/throw como algunos otros lenguajes, pero no quiere decir que no hay manejo de excepciones, Perl puede capturar y manejar las excepciones tan bien como cualquier otro lenguaje solo que las estructuras son ligeramente diferentes.&lt;br /&gt;&lt;br /&gt;El manejo de excepciones en Perl se basa en el uso del operador &lt;code&gt;eval&lt;/code&gt;, que permite &lt;code&gt;eval&lt;/code&gt;uar código y capturar errores, cuando &lt;code&gt;eval&lt;/code&gt; recibe una cadena de caracteres, compila el código que esta en la cadena y lo ejecuta, sin embargo cualquier error que suceda en este código, desde la compilación hasta la ejecución abortará únicamente el &lt;code&gt;eval&lt;/code&gt; y nuestro programa seguirá funcionando, por ejemplo:&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;span style="color: brown;"&gt;1 &lt;/span&gt;&lt;span style="color: #a020f0;"&gt;use &lt;/span&gt;Modern::Perl;&lt;br /&gt;&lt;span style="color: brown;"&gt;2 &lt;/span&gt;&lt;span style="color: brown;"&gt;&lt;b&gt;my&lt;/b&gt;&lt;/span&gt; &lt;span style="color: darkcyan;"&gt;$result&lt;/span&gt; = &lt;span style="color: brown;"&gt;&lt;b&gt;eval&lt;/b&gt;&lt;/span&gt;( &lt;span style="color: magenta;"&gt;"&lt;/span&gt;&lt;span style="color: magenta;"&gt;5 / 0&lt;/span&gt;&lt;span style="color: magenta;"&gt;"&lt;/span&gt; );&lt;br /&gt;&lt;span style="color: brown;"&gt;3 &lt;/span&gt;say &lt;span style="color: magenta;"&gt;"&lt;/span&gt;&lt;span style="color: magenta;"&gt;El resultado es: &lt;/span&gt;&lt;span style="color: darkcyan;"&gt;$result&lt;/span&gt;&lt;span style="color: magenta;"&gt;"&lt;/span&gt;;&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;Aunque el programa funciona, el resultado del &lt;code&gt;eval&lt;/code&gt; es &lt;code&gt;undef&lt;/code&gt;, porque la división por cero evitó que se retorne algún valor, esto además causa una advertencia en la línea 3 sobre la concatenación con una variable indefinida.&lt;br /&gt;&lt;br /&gt;Lo que necesitamos es saber si el &lt;code&gt;eval&lt;/code&gt; fué exitoso o no, y eso esta en la variable especial &lt;code&gt;$@&lt;/code&gt; (tambien conocida como &lt;code&gt;$EVAL_ERROR&lt;/code&gt; si usamos el módulo English).&lt;br /&gt;&lt;br /&gt;Así que para capturar la excepción solo verificamos &lt;code&gt;$@&lt;/code&gt; después del &lt;code&gt;eval&lt;/code&gt;:&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;span style="color: brown;"&gt;1 &lt;/span&gt;&lt;span style="color: #a020f0;"&gt;use &lt;/span&gt;Modern::Perl;&lt;br /&gt;&lt;span style="color: brown;"&gt;2 &lt;/span&gt;&lt;span style="color: brown;"&gt;&lt;b&gt;my&lt;/b&gt;&lt;/span&gt; &lt;span style="color: darkcyan;"&gt;$result&lt;/span&gt; = &lt;span style="color: brown;"&gt;&lt;b&gt;eval&lt;/b&gt;&lt;/span&gt;( &lt;span style="color: magenta;"&gt;"&lt;/span&gt;&lt;span style="color: magenta;"&gt;5 / 0&lt;/span&gt;&lt;span style="color: magenta;"&gt;"&lt;/span&gt; );&lt;br /&gt;&lt;span style="color: brown;"&gt;3 &lt;/span&gt;&lt;span style="color: brown;"&gt;&lt;b&gt;if&lt;/b&gt;&lt;/span&gt; ( &lt;span style="color: darkcyan;"&gt;$@&lt;/span&gt; ) {&lt;br /&gt;&lt;span style="color: brown;"&gt;4 &lt;/span&gt;    say &lt;span style="color: magenta;"&gt;"&lt;/span&gt;&lt;span style="color: magenta;"&gt;Ooops: &lt;/span&gt;&lt;span style="color: darkcyan;"&gt;$@&lt;/span&gt;&lt;span style="color: magenta;"&gt;"&lt;/span&gt;;&lt;br /&gt;&lt;span style="color: brown;"&gt;5 &lt;/span&gt;}&lt;br /&gt;&lt;span style="color: brown;"&gt;6 &lt;/span&gt;&lt;span style="color: brown;"&gt;&lt;b&gt;else&lt;/b&gt;&lt;/span&gt; {&lt;br /&gt;&lt;span style="color: brown;"&gt;7 &lt;/span&gt;    say &lt;span style="color: magenta;"&gt;"&lt;/span&gt;&lt;span style="color: magenta;"&gt;El resultado es: &lt;/span&gt;&lt;span style="color: darkcyan;"&gt;$result&lt;/span&gt;&lt;span style="color: magenta;"&gt;"&lt;/span&gt;;&lt;br /&gt;&lt;span style="color: brown;"&gt;8 &lt;/span&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;Lo que captura el error, el problema con esta solución es que el código que está dentro del string no se verifica a tiempo de compilación, sino que se compila al momento de ejecutarse, y aunque esto es sumamente poderoso, en la mayoría de los casos lo que nos interesa de &lt;code&gt;eval&lt;/code&gt; es la capacidad de capturar errores, para ello la segunda forma de &lt;code&gt;eval&lt;/code&gt;, recibe un bloque de código que se verifica durante la compilación del programa, y la podemos usar así:&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;span style="color: brown;"&gt;2 &lt;/span&gt;&lt;span style="color: brown;"&gt;&lt;b&gt;my&lt;/b&gt;&lt;/span&gt; &lt;span style="color: darkcyan;"&gt;$result&lt;/span&gt; = &lt;span style="color: brown;"&gt;&lt;b&gt;eval&lt;/b&gt;&lt;/span&gt; { &lt;span style="color: magenta;"&gt;5&lt;/span&gt; / &lt;span style="color: magenta;"&gt;0&lt;/span&gt; };&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;En esta forma de eval las llaves (&lt;code&gt;{}&lt;/code&gt;) marcan el bloque donde se requiere capturar excepciones y retorna la última expresión del bloque, o &lt;code&gt;undef&lt;/code&gt; si sucede algún error de ejecución (porque los errores de sintaxis ya fueron capturados durante la compilación del programa).&lt;br /&gt;&lt;br /&gt;La ultima primitiva que necesitamos para completar el sistema de excepciones de Perl es &lt;code&gt;die&lt;/code&gt;, que permite lanzar una excepción, esta rutina recibe un valor que se asigna a la variable especial &lt;code&gt;$@&lt;/code&gt;, así que podríamos hacer un programa que lanza una excepción así:&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;span style="color: brown;"&gt; 1 &lt;/span&gt;&lt;span style="color: #a020f0;"&gt;use &lt;/span&gt;Modern::Perl;&lt;br /&gt;&lt;span style="color: brown;"&gt; 2 &lt;/span&gt;&lt;span style="color: #a020f0;"&gt;use &lt;/span&gt;IO::File;&lt;br /&gt;&lt;span style="color: brown;"&gt; 3 &lt;/span&gt;&lt;br /&gt;&lt;span style="color: brown;"&gt; 4 &lt;/span&gt;&lt;span style="color: brown;"&gt;&lt;b&gt;eval&lt;/b&gt;&lt;/span&gt; {&lt;br /&gt;&lt;span style="color: brown;"&gt; 5 &lt;/span&gt;    &lt;span style="color: brown;"&gt;&lt;b&gt;my&lt;/b&gt;&lt;/span&gt; &lt;span style="color: darkcyan;"&gt;$fh&lt;/span&gt; = IO::File-&amp;gt;&lt;span style="color: brown;"&gt;&lt;b&gt;new&lt;/b&gt;&lt;/span&gt;(&lt;span style="color: magenta;"&gt;"&lt;/span&gt;&lt;span style="color: magenta;"&gt;AlgunArchivo.txt&lt;/span&gt;&lt;span style="color: magenta;"&gt;"&lt;/span&gt;, &lt;span style="color: magenta;"&gt;"&lt;/span&gt;&lt;span style="color: magenta;"&gt;r&lt;/span&gt;&lt;span style="color: magenta;"&gt;"&lt;/span&gt;);&lt;br /&gt;&lt;span style="color: brown;"&gt; 6 &lt;/span&gt;    &lt;span style="color: brown;"&gt;&lt;b&gt;die&lt;/b&gt;&lt;/span&gt;(&lt;span style="color: magenta;"&gt;"&lt;/span&gt;&lt;span style="color: magenta;"&gt;No se puede abrir&lt;/span&gt;&lt;span style="color: magenta;"&gt;"&lt;/span&gt;) &lt;span style="color: brown;"&gt;&lt;b&gt;unless&lt;/b&gt;&lt;/span&gt; &lt;span style="color: darkcyan;"&gt;$fh&lt;/span&gt;;&lt;br /&gt;&lt;span style="color: brown;"&gt; 7 &lt;/span&gt;};&lt;br /&gt;&lt;span style="color: brown;"&gt; 8 &lt;/span&gt;&lt;span style="color: brown;"&gt;&lt;b&gt;if&lt;/b&gt;&lt;/span&gt; ( &lt;span style="color: darkcyan;"&gt;$@&lt;/span&gt; ) {&lt;br /&gt;&lt;span style="color: brown;"&gt; 9 &lt;/span&gt;    say &lt;span style="color: magenta;"&gt;"&lt;/span&gt;&lt;span style="color: magenta;"&gt;Ooops: &lt;/span&gt;&lt;span style="color: darkcyan;"&gt;$@&lt;/span&gt;&lt;span style="color: magenta;"&gt;"&lt;/span&gt;;&lt;br /&gt;&lt;span style="color: brown;"&gt;10 &lt;/span&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;Para algunos esta forma de capturar excepciones puede parecer &lt;a href="http://perliscopio.blogspot.com/2009/08/perl-arcaico.html"&gt;arcáica&lt;/a&gt;, sin embargo, es tan buena como cualquier otra y con las facilidades de Perl podríamos utilizarla como base para implementar una estructura similar a la de otros lenguajes, es decir algo como try/catch. Como ya he comentado en otras oportunidades Perl es un lenguaje excelente para implementar nuevas características en base a las primitivas del lenguaje, y para divertirnos un rato podemos hacernos nuestra propia versión de try/catch:&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;code&gt;&lt;span style="color: brown;"&gt;&amp;nbsp;1 &lt;/span&gt;&lt;span style="color: brown;"&gt;&lt;b&gt;use &lt;/b&gt;&lt;/span&gt;Modern::Perl;&lt;br /&gt;&lt;span style="color: brown;"&gt;&amp;nbsp;2 &lt;/span&gt;&lt;span style="color: brown;"&gt;&lt;b&gt;use &lt;/b&gt;&lt;/span&gt;IO::File;&lt;br /&gt;&lt;span style="color: brown;"&gt;&amp;nbsp;3 &lt;/span&gt;&lt;br /&gt;&lt;span style="color: brown;"&gt;&amp;nbsp;4 &lt;/span&gt;&lt;span style="color: brown;"&gt;&lt;b&gt;sub&lt;/b&gt;&lt;/span&gt;&lt;span style="color: darkcyan;"&gt;&amp;nbsp;&lt;/span&gt;&lt;span style="color: darkcyan;"&gt;try&lt;/span&gt;&lt;span style="color: darkcyan;"&gt;(&amp;amp;amp;)&lt;/span&gt;&lt;span style="color: darkcyan;"&gt;&amp;nbsp;&lt;/span&gt;{&lt;br /&gt;&lt;span style="color: brown;"&gt;&amp;nbsp;5 &lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style="color: brown;"&gt;&lt;b&gt;eval&lt;/b&gt;&lt;/span&gt;&amp;nbsp;{ &lt;span style="color: brown;"&gt;&lt;b&gt;shift&lt;/b&gt;&lt;/span&gt;-&lt;span style="color: darkcyan;"&gt;&amp;amp;gt&lt;/span&gt;;() };&lt;br /&gt;&lt;span style="color: brown;"&gt;&amp;nbsp;6 &lt;/span&gt;}&lt;br /&gt;&lt;span style="color: brown;"&gt;&amp;nbsp;7 &lt;/span&gt;&lt;br /&gt;&lt;span style="color: brown;"&gt;&amp;nbsp;8 &lt;/span&gt;&lt;span style="color: brown;"&gt;&lt;b&gt;sub&lt;/b&gt;&lt;/span&gt;&lt;span style="color: darkcyan;"&gt;&amp;nbsp;&lt;/span&gt;&lt;span style="color: darkcyan;"&gt;catch&lt;/span&gt;&lt;span style="color: darkcyan;"&gt;(&amp;amp;amp;)&lt;/span&gt;&lt;span style="color: darkcyan;"&gt;&amp;nbsp;&lt;/span&gt;{&lt;br /&gt;&lt;span style="color: brown;"&gt;&amp;nbsp;9 &lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style="color: brown;"&gt;&lt;b&gt;if&lt;/b&gt;&lt;/span&gt;&amp;nbsp;( &lt;span style="color: darkcyan;"&gt;$@&lt;/span&gt;&amp;nbsp;) {&lt;br /&gt;&lt;span style="color: brown;"&gt;10 &lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style="color: brown;"&gt;&lt;b&gt;local&lt;/b&gt;&lt;/span&gt;&amp;nbsp;&lt;span style="color: darkcyan;"&gt;$_&lt;/span&gt;&amp;nbsp;= &lt;span style="color: darkcyan;"&gt;$@&lt;/span&gt;;&lt;br /&gt;&lt;span style="color: brown;"&gt;11 &lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style="color: brown;"&gt;&lt;b&gt;shift&lt;/b&gt;&lt;/span&gt;-&lt;span style="color: darkcyan;"&gt;&amp;amp;gt&lt;/span&gt;;();&lt;br /&gt;&lt;span style="color: brown;"&gt;12 &lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}&lt;br /&gt;&lt;span style="color: brown;"&gt;13 &lt;/span&gt;}&lt;br /&gt;&lt;span style="color: brown;"&gt;14 &lt;/span&gt;&lt;br /&gt;&lt;span style="color: brown;"&gt;15 &lt;/span&gt;try {&lt;br /&gt;&lt;span style="color: brown;"&gt;16 &lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style="color: brown;"&gt;&lt;b&gt;my&lt;/b&gt;&lt;/span&gt;&amp;nbsp;&lt;span style="color: darkcyan;"&gt;$fh&lt;/span&gt;&amp;nbsp;= IO::File-&lt;span style="color: darkcyan;"&gt;&amp;amp;gt&lt;/span&gt;;&lt;span style="color: brown;"&gt;&lt;b&gt;new&lt;/b&gt;&lt;/span&gt;( &lt;span style="color: magenta;"&gt;"&lt;/span&gt;&lt;span style="color: magenta;"&gt;AlgunArchivo.txt&lt;/span&gt;&lt;span style="color: magenta;"&gt;"&lt;/span&gt;, &lt;span style="color: magenta;"&gt;"&lt;/span&gt;&lt;span style="color: magenta;"&gt;r&lt;/span&gt;&lt;span style="color: magenta;"&gt;"&lt;/span&gt;&amp;nbsp;);&lt;br /&gt;&lt;span style="color: brown;"&gt;17 &lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style="color: brown;"&gt;&lt;b&gt;die&lt;/b&gt;&lt;/span&gt;(&lt;span style="color: magenta;"&gt;"&lt;/span&gt;&lt;span style="color: magenta;"&gt;No se puede abrir&lt;/span&gt;&lt;span style="color: magenta;"&gt;"&lt;/span&gt;) &lt;span style="color: brown;"&gt;&lt;b&gt;unless&lt;/b&gt;&lt;/span&gt;&amp;nbsp;&lt;span style="color: darkcyan;"&gt;$fh&lt;/span&gt;;&lt;br /&gt;&lt;span style="color: brown;"&gt;18 &lt;/span&gt;};&lt;br /&gt;&lt;span style="color: brown;"&gt;19 &lt;/span&gt;catch {&lt;br /&gt;&lt;span style="color: brown;"&gt;20 &lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;say &lt;span style="color: magenta;"&gt;"&lt;/span&gt;&lt;span style="color: magenta;"&gt;Ooops: &lt;/span&gt;&lt;span style="color: darkcyan;"&gt;$_&lt;/span&gt;&lt;span style="color: magenta;"&gt;"&lt;/span&gt;;&lt;br /&gt;&lt;span style="color: brown;"&gt;21 &lt;/span&gt;};&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;Aquí el prototipo &lt;code&gt;&amp;amp;&lt;/code&gt; de Perl permite hacer que las subrutinas &lt;code&gt;try&lt;/code&gt; y &lt;code&gt;catch&lt;/code&gt; reciban una clausura, pero el prototipo permite eliminar la declaración &lt;code&gt;sub&lt;/code&gt;, aparentando que &lt;code&gt;try&lt;/code&gt; y &lt;code&gt;catch&lt;/code&gt; son estructuras de control que tiene bloque de código asociado.&lt;br /&gt;&lt;br /&gt;Como en realidad son subrutinas cuyo primer parámetro es una clausura, se pueden invocar y así en la línea 5 se extrae el primer argumento (con shift) y se ejecuta la calusura (con -&amp;gt;()), todo dentro de un &lt;code&gt;eval&lt;/code&gt;, si ocurre alguna excepción, se aborta el &lt;code&gt;eval&lt;/code&gt; y se termina el &lt;code&gt;try&lt;/code&gt;.&lt;br /&gt;&lt;br /&gt;Cuando se usa &lt;code&gt;catch&lt;/code&gt; después de un &lt;code&gt;try&lt;/code&gt;, cualquier valor de $@ se localiza en $_ y se ejecuta la clausura, en la cual se puede usar $_ como valor de la excepción.&lt;br /&gt;&lt;br /&gt;Para hacer una extensión que permita utilizar las primitivas recién creadas, solo tenemos que hacer un nuevo módulo, al que llamaré MyTryCatch y que debe estar en el archivo "MyTryCatch.pm":&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;span style="color: brown;"&gt; 1 &lt;/span&gt;&lt;span style="color: brown;"&gt;&lt;b&gt;package&lt;/b&gt;&lt;/span&gt;&lt;span style="color: seagreen;"&gt;&lt;b&gt; MyTryCatch;&lt;/b&gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="color: brown;"&gt; 2 &lt;/span&gt;&lt;br /&gt;&lt;span style="color: brown;"&gt; 3 &lt;/span&gt;&lt;span style="color: #a020f0;"&gt;use &lt;/span&gt;Exporter;&lt;br /&gt;&lt;span style="color: brown;"&gt; 4 &lt;/span&gt;&lt;br /&gt;&lt;span style="color: brown;"&gt; 5 &lt;/span&gt;&lt;span style="color: brown;"&gt;&lt;b&gt;our&lt;/b&gt;&lt;/span&gt; &lt;span style="color: darkcyan;"&gt;$VERSION&lt;/span&gt; = &lt;span style="color: magenta;"&gt;"&lt;/span&gt;&lt;span style="color: magenta;"&gt;1.000&lt;/span&gt;&lt;span style="color: magenta;"&gt;"&lt;/span&gt;;&lt;br /&gt;&lt;span style="color: brown;"&gt; 6 &lt;/span&gt;&lt;span style="color: brown;"&gt;&lt;b&gt;our&lt;/b&gt;&lt;/span&gt; &lt;span style="color: darkcyan;"&gt;@EXPORT_OK&lt;/span&gt; = &lt;span style="color: magenta;"&gt;qw(&lt;/span&gt;&lt;span style="color: magenta;"&gt; try catch &lt;/span&gt;&lt;span style="color: magenta;"&gt;)&lt;/span&gt;;&lt;br /&gt;&lt;span style="color: brown;"&gt; 7 &lt;/span&gt;&lt;span style="color: brown;"&gt;&lt;b&gt;our&lt;/b&gt;&lt;/span&gt; &lt;span style="color: darkcyan;"&gt;@EXPORT&lt;/span&gt; = &lt;span style="color: darkcyan;"&gt;@EXPORT_OK&lt;/span&gt;;&lt;br /&gt;&lt;span style="color: brown;"&gt; 8 &lt;/span&gt;&lt;br /&gt;&lt;span style="color: brown;"&gt; 9 &lt;/span&gt;&lt;span style="color: brown;"&gt;&lt;b&gt;sub&lt;/b&gt;&lt;/span&gt;&lt;span style="color: darkcyan;"&gt; &lt;/span&gt;&lt;span style="color: darkcyan;"&gt;try(&lt;/span&gt;&lt;span style="color: darkcyan;"&gt;&amp;amp;) &lt;/span&gt;{&lt;br /&gt;&lt;span style="color: brown;"&gt;10 &lt;/span&gt;    &lt;span style="color: brown;"&gt;&lt;b&gt;eval&lt;/b&gt;&lt;/span&gt; { &lt;span style="color: brown;"&gt;&lt;b&gt;shift&lt;/b&gt;&lt;/span&gt;-&amp;gt;() };&lt;br /&gt;&lt;span style="color: brown;"&gt;11 &lt;/span&gt;}&lt;br /&gt;&lt;span style="color: brown;"&gt;12 &lt;/span&gt;&lt;br /&gt;&lt;span style="color: brown;"&gt;13 &lt;/span&gt;&lt;span style="color: brown;"&gt;&lt;b&gt;sub&lt;/b&gt;&lt;/span&gt;&lt;span style="color: darkcyan;"&gt; &lt;/span&gt;&lt;span style="color: darkcyan;"&gt;catch(&lt;/span&gt;&lt;span style="color: darkcyan;"&gt;&amp;amp;) &lt;/span&gt;{&lt;br /&gt;&lt;span style="color: brown;"&gt;14 &lt;/span&gt;    &lt;span style="color: brown;"&gt;&lt;b&gt;local&lt;/b&gt;&lt;/span&gt; &lt;span style="color: darkcyan;"&gt;$_&lt;/span&gt; = &lt;span style="color: darkcyan;"&gt;$@&lt;/span&gt;;&lt;br /&gt;&lt;span style="color: brown;"&gt;15 &lt;/span&gt;    &lt;span style="color: brown;"&gt;&lt;b&gt;shift&lt;/b&gt;&lt;/span&gt;-&amp;gt;();&lt;br /&gt;&lt;span style="color: brown;"&gt;16 &lt;/span&gt;}&lt;br /&gt;&lt;span style="color: brown;"&gt;17 &lt;/span&gt;&lt;br /&gt;&lt;span style="color: brown;"&gt;18 &lt;/span&gt;&lt;span style="color: magenta;"&gt;1&lt;/span&gt;;&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;Luego cada vez que necesite usar la nueva estructura de control solo tengo que incluirla en un programa, por ejemplo:&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;code&gt;&lt;span style="color: brown;"&gt;&amp;nbsp;1 &lt;/span&gt;&lt;span style="color: brown;"&gt;&lt;b&gt;package&lt;/b&gt;&lt;/span&gt;&lt;span style="color: seagreen;"&gt;&lt;b&gt;&amp;nbsp;MyTryCatch;&lt;/b&gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="color: brown;"&gt;&amp;nbsp;2 &lt;/span&gt;&lt;br /&gt;&lt;span style="color: brown;"&gt;&amp;nbsp;3 &lt;/span&gt;&lt;span style="color: brown;"&gt;&lt;b&gt;use &lt;/b&gt;&lt;/span&gt;Exporter;&lt;br /&gt;&lt;span style="color: brown;"&gt;&amp;nbsp;4 &lt;/span&gt;&lt;br /&gt;&lt;span style="color: brown;"&gt;&amp;nbsp;5 &lt;/span&gt;&lt;span style="color: brown;"&gt;&lt;b&gt;our&lt;/b&gt;&lt;/span&gt;&amp;nbsp;&lt;span style="color: darkcyan;"&gt;$VERSION&lt;/span&gt;&amp;nbsp;= &lt;span style="color: magenta;"&gt;"&lt;/span&gt;&lt;span style="color: magenta;"&gt;1.000&lt;/span&gt;&lt;span style="color: magenta;"&gt;"&lt;/span&gt;;&lt;br /&gt;&lt;span style="color: brown;"&gt;&amp;nbsp;6 &lt;/span&gt;&lt;span style="color: brown;"&gt;&lt;b&gt;our&lt;/b&gt;&lt;/span&gt;&amp;nbsp;&lt;span style="color: darkcyan;"&gt;@EXPORT_OK&lt;/span&gt;&amp;nbsp;= &lt;span style="color: magenta;"&gt;qw(&lt;/span&gt;&lt;span style="color: magenta;"&gt;&amp;nbsp;try catch &lt;/span&gt;&lt;span style="color: magenta;"&gt;)&lt;/span&gt;;&lt;br /&gt;&lt;span style="color: brown;"&gt;&amp;nbsp;7 &lt;/span&gt;&lt;span style="color: brown;"&gt;&lt;b&gt;our&lt;/b&gt;&lt;/span&gt;&amp;nbsp;&lt;span style="color: darkcyan;"&gt;@EXPORT&lt;/span&gt;&amp;nbsp;= &lt;span style="color: darkcyan;"&gt;@EXPORT_OK&lt;/span&gt;;&lt;br /&gt;&lt;span style="color: brown;"&gt;&amp;nbsp;8 &lt;/span&gt;&lt;br /&gt;&lt;span style="color: brown;"&gt;&amp;nbsp;9 &lt;/span&gt;&lt;span style="color: brown;"&gt;&lt;b&gt;sub&lt;/b&gt;&lt;/span&gt;&lt;span style="color: darkcyan;"&gt;&amp;nbsp;&lt;/span&gt;&lt;span style="color: darkcyan;"&gt;try&lt;/span&gt;&lt;span style="color: darkcyan;"&gt;(&amp;amp;amp;)&lt;/span&gt;&lt;span style="color: darkcyan;"&gt;&amp;nbsp;&lt;/span&gt;{&lt;br /&gt;&lt;span style="color: brown;"&gt;10 &lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style="color: brown;"&gt;&lt;b&gt;eval&lt;/b&gt;&lt;/span&gt;&amp;nbsp;{ &lt;span style="color: brown;"&gt;&lt;b&gt;shift&lt;/b&gt;&lt;/span&gt;-&lt;span style="color: darkcyan;"&gt;&amp;amp;gt&lt;/span&gt;;() };&lt;br /&gt;&lt;span style="color: brown;"&gt;11 &lt;/span&gt;}&lt;br /&gt;&lt;span style="color: brown;"&gt;12 &lt;/span&gt;&lt;br /&gt;&lt;span style="color: brown;"&gt;13 &lt;/span&gt;&lt;span style="color: brown;"&gt;&lt;b&gt;sub&lt;/b&gt;&lt;/span&gt;&lt;span style="color: darkcyan;"&gt;&amp;nbsp;&lt;/span&gt;&lt;span style="color: darkcyan;"&gt;catch&lt;/span&gt;&lt;span style="color: darkcyan;"&gt;(&amp;amp;amp;)&lt;/span&gt;&lt;span style="color: darkcyan;"&gt;&amp;nbsp;&lt;/span&gt;{&lt;br /&gt;&lt;span style="color: brown;"&gt;14 &lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style="color: brown;"&gt;&lt;b&gt;if&lt;/b&gt;&lt;/span&gt;&amp;nbsp;( &lt;span style="color: darkcyan;"&gt;$@&lt;/span&gt;&amp;nbsp;) {&lt;br /&gt;&lt;span style="color: brown;"&gt;15 &lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style="color: brown;"&gt;&lt;b&gt;local&lt;/b&gt;&lt;/span&gt;&amp;nbsp;&lt;span style="color: darkcyan;"&gt;$_&lt;/span&gt;&amp;nbsp;= &lt;span style="color: darkcyan;"&gt;$@&lt;/span&gt;;&lt;br /&gt;&lt;span style="color: brown;"&gt;16 &lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style="color: brown;"&gt;&lt;b&gt;shift&lt;/b&gt;&lt;/span&gt;-&lt;span style="color: darkcyan;"&gt;&amp;amp;gt&lt;/span&gt;;();&lt;br /&gt;&lt;span style="color: brown;"&gt;17 &lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}&lt;br /&gt;&lt;span style="color: brown;"&gt;18 &lt;/span&gt;}&lt;/code&gt;&lt;code&gt;&lt;br /&gt;&lt;span style="color: brown;"&gt;19&lt;/span&gt;&lt;/code&gt;&lt;br /&gt;&lt;code&gt;&lt;span style="color: brown;"&gt;20 &lt;/span&gt;&lt;span style="color: magenta;"&gt;1&lt;/span&gt;;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;Las primitivas de que acabamos de crear tienen algunos defectos, por ejemplo puede usarse &lt;code&gt;catch&lt;/code&gt; sin &lt;code&gt;try&lt;/code&gt;, y una instrucción return dentro de un bloque &lt;code&gt;try&lt;/code&gt; o &lt;code&gt;catch&lt;/code&gt;, se sale del bloque y no de la subrutina donde se declara la estructura de captura de excepciones, entre otros. Sin embargo con algo más de esfuerzo podríamos hacer una extensión que declare una estructura que se comporte mejor.&lt;br /&gt;&lt;br /&gt;En el CPAN hay varios módulos que permiten manejar errores con estructuras similares, desde los más sencillos como &lt;a href="http://search.cpan.org/perldoc?Try::Tiny"&gt;&lt;code&gt;Try::Tiny&lt;/code&gt;&lt;/a&gt;, que sufre de algunos de los inconvenientes de &lt;code&gt;MyTryCatch&lt;/code&gt; hasta los más complejos como &lt;a href="http://search.cpan.org/perldoc?TryCatch"&gt;&lt;code&gt;TryCatch&lt;/code&gt;&lt;/a&gt; que usa magia de la buena como &lt;a href="http://search.cpan.org/perldoc?Devel::Declare"&gt;&lt;code&gt;Devel::Declare&lt;/code&gt;&lt;/a&gt; para hacer una estructura de manejo de excepciones con casi cualquier cosa que se te pueda imaginar.&lt;br /&gt;&lt;br /&gt;Si tus requerimientos no son muy exigentes mi recomendación es utilizar &lt;code&gt;Try::Tiny&lt;/code&gt;, es realmente minúscula, casi no tiene dependencias y es muy fácil de instalar, por otra parte si quieres un sistema de manejo de excepciones que hace de todo, no te importa mucho el consumo de recursos y tienes la paciencia para instalar docenas de módulos, puedes usar &lt;code&gt;TryCatch&lt;/code&gt;.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5238463735728501931-3861835314264816460?l=perliscopio.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://perliscopio.blogspot.com/feeds/3861835314264816460/comments/default' title='Enviar comentarios'/><link rel='replies' type='text/html' href='http://perliscopio.blogspot.com/2009/11/manejando-errores-en-perl.html#comment-form' title='0 comentarios'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5238463735728501931/posts/default/3861835314264816460'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5238463735728501931/posts/default/3861835314264816460'/><link rel='alternate' type='text/html' href='http://perliscopio.blogspot.com/2009/11/manejando-errores-en-perl.html' title='Manejando errores en Perl'/><author><name>Jose Rey</name><uri>http://www.blogger.com/profile/15071755167581242815</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5238463735728501931.post-9106985785414958406</id><published>2009-10-24T10:01:00.002-04:30</published><updated>2009-10-24T10:20:53.457-04:30</updated><category scheme='http://www.blogger.com/atom/ns#' term='Perl'/><title type='text'>Evolución de lenguajes</title><content type='html'>[&lt;a href="http://perliscope.blogspot.com/2009/10/language-evolution.html"&gt;English translation&lt;/a&gt;]&lt;br /&gt;Tal vez se ha notado que no he escrito mucho últimamente, la razón fue que tuve que dedicarme por completo una migración de emergencia.&lt;br /&gt;El sistema en cuestión pertenece al cliente que me contrató para desarrollar una aplicación web, que casualmente fue mi primera aplicación de este estilo allá por 1998.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;En aquella época estaba dando mis primeros pasos con Perl, pero de alguna manera me convencieron de que la aplicación debía desarrollarse en PHP, poco a poco me dí cuenta que PHP no era lo suficientemente flexible y termine haciendo varios programas en Perl que implementaban la mayor parte de la funcionalidad, aún así toda la interfaz de la aplicación se quedó en PHP.&lt;br /&gt;&lt;br /&gt;Durante este proyecto aprendí que Perl era mucho más versátil, poderoso y divertido que PHP, y si no me hubiera dejado convencer, probablemente hubiera conseguido CGI.pm, toda la aplicación estaría en Perl y no tendría una historia para contar.&lt;br /&gt;&lt;br /&gt;Al comenzar la migración se me ocurrió que sería más fácil poner a funcionar primero la interfaz, ya que pensé que siendo la parte más simple de la aplicación podría migrarla fácilmente a PHP5, nada más alejado de la realidad, nada funcionaba como debía.&lt;br /&gt;&lt;br /&gt;Entiendo que todo evoluciona, pero es que los programas ni siquiera compilaban, algunos APIs han cambiado lo suficiente como para necesitar una completa revisión de todo el código fuente, y por supuesto el programa era un asco, ¿que otra cosa podría ser?, en aquella época no había una librería de templates, el acceso a la base de datos se hacía con las horribles funciones de la librería de PHP3, y toda la aplicación es un monumento a la programación estilo ASP, donde la vista, el modelo y los controladores estaban completamente integrados, como si los hubieran pasado por una licuadora.&lt;br /&gt;&lt;br /&gt;Lo cierto es que fue más fácil compilar PHP3 en el nuevo sistema operativo que intentar migrar el código a PHP5, por lo que doy gracias a Debian y particularmente a archive.debian.org, que debe ser uno de los pocos sitios en el planeta que todavía guardan las fuentes de eso (PHP3), porque la comunidad del lenguaje tiene una política de retirarlas de internet.&lt;br /&gt;&lt;br /&gt;Una vez superado el problema (es decir PHP), tenía pesadillas sobre el montón de código Perl 5 que no funcionaría para nada en el nuevo Perl 5.10, así que comencé resignado a copiar todos los archivos.&lt;br /&gt;&lt;br /&gt;Lo primero en fallar fue DBI, en efecto la cadena de conexión a la base de datos utilizaba un formato que ni recordaba que existió:&lt;br /&gt;&lt;pre&gt;&lt;code&gt;&lt;br /&gt;  DBI-&amp;gt;connect("dbi:Pg:dbname=mydb@myhost.com", "user", "pass");&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;una vez que la cambié por la sintaxis actual:&lt;br /&gt;&lt;pre&gt;&lt;code&gt;&lt;br /&gt;  DBI-&amp;gt;connect("dbi:Pg:dbname=mydb;host=myhost.com", "user", "pass");&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;Probé nuevamente el programa y todo funcionó, procedí a probar otro programa y todo funcionó, así seguí programa por programa sin encontrar ninguna falla, ni una más.&lt;br /&gt;&lt;br /&gt;Una década de evolución del lenguaje y del CPAN y casi todo funcionó a la primera, estaba asombrado (y por supuesto complacido).&lt;br /&gt;&lt;br /&gt;Al contrastar la evolución de Perl y PHP en el tiempo puedo apreciar que mientras el primero ha adquirido una gran cantidad de características, como nuevas construcciones del lenguaje, varios sistemas de implementación de concurrencia, desde la programación orientada a eventos hasta los threads pasando por las corrutinas, nuevas abstracciones para facilitar y mejorar la OOP que permiten al programador elegir entre varios sistemas de orientación a objetos, avances importantes en el área de meta programación, y algunos otros, el segundo básicamente ha obtenido un sistema de OOP, y aún así es más incompatible que Perl.&lt;br /&gt;&lt;br /&gt;La pregunta es: ¿por qué esta diferencia radical?, sobre todo cuando se dice que hay muchas más soluciones listas en PHP que en Perl y se supone que debería haber un mayor desarrollo para el primero.&lt;br /&gt;&lt;br /&gt;Puede dar la impresión de que lo que digo pretende hacer leña de PHP, pero no es así, PHP fue solo el disparador que me hizo pensar en el problema, si tomáramos otros lenguajes, probablemente llegaría a conclusiones similares, por ejemplo: ¿cuanta evolución ha tenido Python en la última década?, y ¿será que un programa de hace 10 años funciona en el ambiente actual?, ¿y en Java?. Yo apuesto a que Perl les gana a ambos en estos frentes.&lt;br /&gt;&lt;br /&gt;Aunque Perl es una &lt;a href="http://es.wikipedia.org/wiki/Worse_is_better"&gt;solución New Jersey&lt;/a&gt;, el lenguaje en sí está muy influenciado por Lisp que es una &lt;a href="http://es.wikipedia.org/wiki/Worse_is_better"&gt;solución MIT&lt;/a&gt;, y aunque se puede argumentar sobre la complejidad de la sintaxis de Perl, lo cierto es que la semántica de sus operaciones es bastante consistente y sumamente versátil, además se puede extender el lenguaje con módulos, permitiendo la experimentación sin necesidad de modificar el interprete.&lt;br /&gt;&lt;br /&gt;Otros ambientes de programación tienen herramientas muy buenas que facilitan enormemente la realización de compiladores, pero el nivel de complejidad en la implementación de alguna extensión, que en general se deben implementar como preprocesadores, limitan el desarrollo de este tipo de extensiones.&lt;br /&gt;&lt;br /&gt;Por otra parte la falta de integración con el compilador obliga al usuario a introducir complejidad en la construcción del software, ejecución de precompiladores, manejo de archivos temporales, y otros, que se convierten en una pesadilla sobre todo en ambientes dinámicos, imaginemos que para para cargar un módulo en Moose, se necesitara ejecutar el precompilador de Moose y luego cargar el módulo resultante de la compilación, sería realmente fastidioso, sin embargo en Perl existen mecanismos que permiten que se ejecute automáticamente el compilador de Moose, que accede al código fuente e ingresa el resultado automáticamente al compilador de Perl para su fase final de compilación, y el usuario lo único que debe hacer es: use Moose; al comenzar un programa.&lt;br /&gt;&lt;br /&gt;Los problemas anteriormente descritos limitan la adopción de extensiones externas al lenguaje, coartando la evolución por la vía de la extensión, que es la manera más fácil de evolucionar un lenguaje. En este sentido Perl se parece mucho a Lisp, y la mayor parte de la evolución del lenguaje se logra agregando módulos externos en el CPAN. Hoy en día existen extensiones que implementan diversas estructuras de control como try/catch, también hay módulos que permiten declarar los parámetros de las subrutinas y los métodos, y&amp;nbsp; muchas otras cosas que no son parte integral del lenguaje.&lt;br /&gt;Con respecto a la compatibilidad, hay dos factores a tomar en cuenta: la compatibilidad de las librerías y la del lenguaje.&lt;br /&gt;&lt;br /&gt;La compatibilidad del lenguaje se mantiene utilizando los pragmas, que en Perl son prácticamente lo mismo que cualquier otro módulo del CPAN (o al menos eso parecen desde la perspectiva de un programador), así que cuando el lenguaje cambia simplemente se introducen pragmas. Un ejemplo son las nuevas características de Perl 5.10 que se activan usando un pragma.&lt;br /&gt;La mayor incompatibilidad que ocurrió en la ultima década es la eliminación de los pseudohashes en Perl, y para minimizar los problemas se crearon mecanismos para facilitar la migración del código existente (use fields) y se mantuvieron los pseudohashes como una característica obsoleta por unos 5 años, lo que ilustra cuan comprometida está la comunidad a mantener la compatibilidad con el código existente.&lt;br /&gt;&lt;br /&gt;La comunidad ha adoptado recientemente el término DarkPAN, que es todo el código que esta escrito en Perl, pero no está a la vista del público, sino que reside escondido en miles de sistemas que la gente ni siquiera sabe que han sido escritos en Perl (el que originó esta historia aparenta estar escrito en PHP), y aunque hay gente que prefiere que la plataforma de Perl se modernice obviando el DarkPAN, la comunidad en general piensa que esa no es la mejor política.&lt;br /&gt;&lt;br /&gt;En el universo la materia obscura es la mayoría de la masa, y aunque no sabemos si el DarkPAN tiene más peso que el CPAN, podemos observar algunos efectos colaterales, por ejemplo: aunque parece haber más sistemas escritos en PHP y Python, se consiguen más ofertas de trabajo en Perl y probablemente la causa sea el DarkPAN.&lt;br /&gt;&lt;br /&gt;Lo cierto es que todo ese código que mueve infinidad de negocios está allí porque funciona y porque se puede mantener en el tiempo con menos esfuerzo que el código desarrollado en otras plataformas.&lt;br /&gt;&lt;br /&gt;Lo más impresionante es que hoy en día tengamos en la misma plataforma compatible con el código de hace una década, librerías tan fáciles de usar, modernas y poderosas como Moose, Devel::Declare y Catalyst, que son la envidia de los desarrolladores de otros lenguajes.&lt;br /&gt;&lt;br /&gt;Así que si quieres programar en un ambiente fácil, moderno, poderoso y perdurable, la elección es clara usar Perl.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5238463735728501931-9106985785414958406?l=perliscopio.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://perliscopio.blogspot.com/feeds/9106985785414958406/comments/default' title='Enviar comentarios'/><link rel='replies' type='text/html' href='http://perliscopio.blogspot.com/2009/10/evolucion-de-lenguajes.html#comment-form' title='0 comentarios'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5238463735728501931/posts/default/9106985785414958406'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5238463735728501931/posts/default/9106985785414958406'/><link rel='alternate' type='text/html' href='http://perliscopio.blogspot.com/2009/10/evolucion-de-lenguajes.html' title='Evolución de lenguajes'/><author><name>Jose Rey</name><uri>http://www.blogger.com/profile/15071755167581242815</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5238463735728501931.post-778355072149523081</id><published>2009-10-05T10:17:00.001-04:30</published><updated>2009-10-14T23:29:57.062-04:30</updated><title type='text'>Calculadora Estadística: Toques finales</title><content type='html'>[&lt;a href="http://perliscope.blogspot.com/2009/10/statistic-calculator-final-console.html"&gt;English translation&lt;/a&gt;]&lt;br /&gt;En el &lt;a href="http://perliscopio.blogspot.com/2009/09/calculadora-estadistica-consola.html"&gt;artículo anterior&lt;/a&gt;. dejamos pendiente lograr que el interpretador reconociera parámetros y fuera capaz de escribir cualquier valor de retorno de las funciones en Statistics::Descriptive.&lt;br /&gt;Primero debemos definir como se separarán los comandos de los parámetros, y como se separarán los parámetros entre sí, y la manera más fácil es hacerlo como el shell, es decir usando espacios en blanco para ambos, así una vez que se obtiene una línea de comandos:&lt;br /&gt;&lt;pre&gt;&lt;span style="color: brown;"&gt;34 &lt;/span&gt;    &lt;span style="color: darkcyan;"&gt;$command&lt;/span&gt; =~ &lt;span style="color: brown;"&gt;&lt;b&gt;s/&lt;/b&gt;&lt;/span&gt;&lt;span style="color: magenta;"&gt;^&lt;/span&gt;&lt;span style="color: slateblue;"&gt;\s&lt;/span&gt;&lt;span style="color: slateblue;"&gt;+&lt;/span&gt;&lt;span style="color: brown;"&gt;&lt;b&gt;//&lt;/b&gt;&lt;/span&gt;; &lt;span style="color: darkcyan;"&gt;$command&lt;/span&gt; =~ &lt;span style="color: brown;"&gt;&lt;b&gt;s/&lt;/b&gt;&lt;/span&gt;&lt;span style="color: slateblue;"&gt;\s&lt;/span&gt;&lt;span style="color: slateblue;"&gt;+&lt;/span&gt;&lt;span style="color: magenta;"&gt;$&lt;/span&gt;&lt;span style="color: brown;"&gt;&lt;b&gt;//&lt;/b&gt;&lt;/span&gt;;&lt;br /&gt;&lt;span style="color: brown;"&gt;35 &lt;/span&gt;    &lt;span style="color: brown;"&gt;&lt;b&gt;my&lt;/b&gt;&lt;/span&gt; &lt;span style="color: darkcyan;"&gt;@args&lt;/span&gt; = &lt;span style="color: brown;"&gt;&lt;b&gt;split&lt;/b&gt;&lt;/span&gt;&lt;span style="color: brown;"&gt;&lt;b&gt; /&lt;/b&gt;&lt;/span&gt;&lt;span style="color: slateblue;"&gt;\s&lt;/span&gt;&lt;span style="color: slateblue;"&gt;+&lt;/span&gt;&lt;span style="color: brown;"&gt;&lt;b&gt;/&lt;/b&gt;&lt;/span&gt;, &lt;span style="color: darkcyan;"&gt;$command&lt;/span&gt;;&lt;br /&gt;&lt;span style="color: brown;"&gt;36 &lt;/span&gt;    &lt;span style="color: brown;"&gt;&lt;b&gt;my&lt;/b&gt;&lt;/span&gt; &lt;span style="color: darkcyan;"&gt;$oper&lt;/span&gt; = looks_like_number( &lt;span style="color: darkcyan;"&gt;$args[&lt;/span&gt;&lt;span style="color: magenta;"&gt;0&lt;/span&gt;&lt;span style="color: darkcyan;"&gt;]&lt;/span&gt; ) ? &lt;span style="color: magenta;"&gt;"&lt;/span&gt;&lt;span style="color: magenta;"&gt;add_data&lt;/span&gt;&lt;span style="color: magenta;"&gt;"&lt;/span&gt; : &lt;span style="color: brown;"&gt;&lt;b&gt;shift&lt;/b&gt;&lt;/span&gt; &lt;span style="color: darkcyan;"&gt;@args&lt;/span&gt;;&lt;/pre&gt;se eliminan los espacios al principio y al final (34), se separan todos los elementos separados por uno o más blancos (35), y se obtiene la operación a realizar (36) que en general es el primer elemento, excepto en el caso de números en que la operación es "add_data". Luego de estas operaciones tenemos la operación a realizar en $oper y sus argumentos en @args, por lo que solamente resta aplicarlos:&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;span style="color: brown;"&gt;38 &lt;/span&gt;        when (&lt;span style="color: darkcyan;"&gt;%FUNCS&lt;/span&gt;)               { apply( &lt;span style="color: darkcyan;"&gt;$oper&lt;/span&gt;, &lt;span style="color: darkcyan;"&gt;@args&lt;/span&gt; ) }&lt;/pre&gt;La rutina a cargo de la aplicación de la operación debe obtener los argumentos (26), evaluar la operación en contexto lista (27), ¿por qué en contexto lista?, para permitir operaciones como "percentile" que produce múltiples valores.&lt;br /&gt;Una vez obtenido el valor calculado, hay que verificar si vale la pena imprimirlo, así que retornamos si @result está vacío (28), o si tiene un solo elemento pero no esta definido o es una cadena vacia (29).&lt;br /&gt;Para desplegar valores complejos utilizaré el formato YAML, porque es muy legible y tengo a disposición el módulo YAML del CPAN.&lt;br /&gt;Así que dependiendo del número de elementos en @result convertiré el primer escalar o todo el arreglo en un texto en YAML antes de imprimirlo (30).&lt;br /&gt;La calculadora de consola finalmente luce así:&lt;br /&gt;&lt;pre&gt;&lt;span style="color: brown;"&gt; 1 &lt;/span&gt;&lt;span style="color: #a020f0;"&gt;#!/usr/bin/perl&lt;/span&gt;&lt;br /&gt;&lt;span style="color: brown;"&gt; 2 &lt;/span&gt;&lt;br /&gt;&lt;span style="color: brown;"&gt; 3 &lt;/span&gt;&lt;span style="color: #a020f0;"&gt;use &lt;/span&gt;Modern::Perl;&lt;br /&gt;&lt;span style="color: brown;"&gt; 4 &lt;/span&gt;&lt;span style="color: #a020f0;"&gt;use &lt;/span&gt;Scalar::Util &lt;span style="color: magenta;"&gt;qw(&lt;/span&gt;&lt;span style="color: magenta;"&gt; looks_like_number &lt;/span&gt;&lt;span style="color: magenta;"&gt;)&lt;/span&gt;;&lt;br /&gt;&lt;span style="color: brown;"&gt; 5 &lt;/span&gt;&lt;span style="color: #a020f0;"&gt;use &lt;/span&gt;Statistics::Descriptive;&lt;br /&gt;&lt;span style="color: brown;"&gt; 6 &lt;/span&gt;&lt;span style="color: #a020f0;"&gt;use &lt;/span&gt;Pod::Perldoc;&lt;br /&gt;&lt;span style="color: brown;"&gt; 7 &lt;/span&gt;&lt;span style="color: #a020f0;"&gt;use &lt;/span&gt;Term::ReadLine;&lt;br /&gt;&lt;span style="color: brown;"&gt; 8 &lt;/span&gt;&lt;span style="color: #a020f0;"&gt;use &lt;/span&gt;YAML;&lt;br /&gt;&lt;span style="color: brown;"&gt; 9 &lt;/span&gt;&lt;br /&gt;&lt;span style="color: brown;"&gt;10 &lt;/span&gt;&lt;span style="color: brown;"&gt;&lt;b&gt;my&lt;/b&gt;&lt;/span&gt; &lt;span style="color: darkcyan;"&gt;$term&lt;/span&gt; = &lt;span style="color: brown;"&gt;&lt;b&gt;new&lt;/b&gt;&lt;/span&gt; Term::ReadLine &lt;span style="color: magenta;"&gt;'&lt;/span&gt;&lt;span style="color: magenta;"&gt;Statistic Calculator&lt;/span&gt;&lt;span style="color: magenta;"&gt;'&lt;/span&gt;;&lt;br /&gt;&lt;span style="color: brown;"&gt;11 &lt;/span&gt;&lt;br /&gt;&lt;span style="color: brown;"&gt;12 &lt;/span&gt;&lt;span style="color: brown;"&gt;&lt;b&gt;my&lt;/b&gt;&lt;/span&gt; &lt;span style="color: darkcyan;"&gt;%FUNCS&lt;/span&gt; = &lt;span style="color: brown;"&gt;&lt;b&gt;map&lt;/b&gt;&lt;/span&gt; { &lt;span style="color: darkcyan;"&gt;$_&lt;/span&gt; =&amp;gt; &lt;span style="color: magenta;"&gt;1&lt;/span&gt; } &lt;span style="color: magenta;"&gt;qw(&lt;/span&gt;&lt;span style="color: magenta;"&gt; sum mean count variance standard_deviation&lt;/span&gt;&lt;br /&gt;&lt;span style="color: brown;"&gt;13 &lt;/span&gt;&lt;span style="color: magenta;"&gt;    min mindex max maxdex sample_range median harmonic_mean geometric_mean&lt;/span&gt;&lt;br /&gt;&lt;span style="color: brown;"&gt;14 &lt;/span&gt;&lt;span style="color: magenta;"&gt;    mode trimmed_mean clear add_data percentile quantile least_squares_fit&lt;/span&gt;&lt;br /&gt;&lt;span style="color: brown;"&gt;15 &lt;/span&gt;&lt;span style="color: magenta;"&gt;    frequency_distribution_ref frequency_distribution&lt;/span&gt;&lt;span style="color: magenta;"&gt;)&lt;/span&gt;;&lt;br /&gt;&lt;span style="color: brown;"&gt;16 &lt;/span&gt;&lt;br /&gt;&lt;span style="color: brown;"&gt;17 &lt;/span&gt;&lt;span style="color: brown;"&gt;&lt;b&gt;my&lt;/b&gt;&lt;/span&gt; &lt;span style="color: darkcyan;"&gt;@COMMANDS&lt;/span&gt; = &lt;span style="color: magenta;"&gt;qw(&lt;/span&gt;&lt;span style="color: magenta;"&gt; exit quit help man &lt;/span&gt;&lt;span style="color: magenta;"&gt;)&lt;/span&gt;;&lt;br /&gt;&lt;span style="color: brown;"&gt;18 &lt;/span&gt;&lt;br /&gt;&lt;span style="color: brown;"&gt;19 &lt;/span&gt;&lt;span style="color: brown;"&gt;&lt;b&gt;sub&lt;/b&gt;&lt;/span&gt;&lt;span style="color: darkcyan;"&gt; &lt;/span&gt;&lt;span style="color: darkcyan;"&gt;help &lt;/span&gt;{ say &lt;span style="color: magenta;"&gt;"&lt;/span&gt;&lt;span style="color: magenta;"&gt;Comandos: &lt;/span&gt;&lt;span style="color: magenta;"&gt;"&lt;/span&gt; . &lt;span style="color: brown;"&gt;&lt;b&gt;join&lt;/b&gt;&lt;/span&gt;( &lt;span style="color: magenta;"&gt;"&lt;/span&gt;&lt;span style="color: magenta;"&gt;, &lt;/span&gt;&lt;span style="color: magenta;"&gt;"&lt;/span&gt;, &lt;span style="color: brown;"&gt;&lt;b&gt;sort&lt;/b&gt;&lt;/span&gt; &lt;span style="color: darkcyan;"&gt;@COMMANDS&lt;/span&gt;, &lt;span style="color: brown;"&gt;&lt;b&gt;keys&lt;/b&gt;&lt;/span&gt; &lt;span style="color: darkcyan;"&gt;%FUNCS&lt;/span&gt; ) }&lt;br /&gt;&lt;span style="color: brown;"&gt;20 &lt;/span&gt;&lt;br /&gt;&lt;span style="color: brown;"&gt;21 &lt;/span&gt;&lt;span style="color: brown;"&gt;&lt;b&gt;sub&lt;/b&gt;&lt;/span&gt;&lt;span style="color: darkcyan;"&gt; &lt;/span&gt;&lt;span style="color: darkcyan;"&gt;man &lt;/span&gt;{ Pod::Perldoc-&amp;gt;&lt;span style="color: brown;"&gt;&lt;b&gt;new&lt;/b&gt;&lt;/span&gt;( &lt;span style="color: magenta;"&gt;args &lt;/span&gt;=&amp;gt; &lt;span style="color: darkcyan;"&gt;\@_&lt;/span&gt; )-&amp;gt;process }&lt;br /&gt;&lt;span style="color: brown;"&gt;22 &lt;/span&gt;&lt;br /&gt;&lt;span style="color: brown;"&gt;23 &lt;/span&gt;&lt;span style="color: brown;"&gt;&lt;b&gt;my&lt;/b&gt;&lt;/span&gt; &lt;span style="color: darkcyan;"&gt;$s&lt;/span&gt; = Statistics::Descriptive::Full-&amp;gt;&lt;span style="color: brown;"&gt;&lt;b&gt;new&lt;/b&gt;&lt;/span&gt;();&lt;br /&gt;&lt;span style="color: brown;"&gt;24 &lt;/span&gt;&lt;br /&gt;&lt;span style="color: brown;"&gt;25 &lt;/span&gt;&lt;span style="color: brown;"&gt;&lt;b&gt;sub&lt;/b&gt;&lt;/span&gt;&lt;span style="color: darkcyan;"&gt; &lt;/span&gt;&lt;span style="color: darkcyan;"&gt;apply &lt;/span&gt;{&lt;br /&gt;&lt;span style="color: brown;"&gt;26 &lt;/span&gt;    &lt;span style="color: brown;"&gt;&lt;b&gt;my&lt;/b&gt;&lt;/span&gt; ( &lt;span style="color: darkcyan;"&gt;$oper&lt;/span&gt;, &lt;span style="color: darkcyan;"&gt;@args&lt;/span&gt; ) = &lt;span style="color: darkcyan;"&gt;@_&lt;/span&gt;;&lt;br /&gt;&lt;span style="color: brown;"&gt;27 &lt;/span&gt;    &lt;span style="color: brown;"&gt;&lt;b&gt;my&lt;/b&gt;&lt;/span&gt; &lt;span style="color: darkcyan;"&gt;@result&lt;/span&gt; = &lt;span style="color: darkcyan;"&gt;$s&lt;/span&gt;-&amp;gt;&lt;span style="color: darkcyan;"&gt;$oper&lt;/span&gt;(&lt;span style="color: darkcyan;"&gt;@args&lt;/span&gt;);&lt;br /&gt;&lt;span style="color: brown;"&gt;28 &lt;/span&gt;    &lt;span style="color: brown;"&gt;&lt;b&gt;return&lt;/b&gt;&lt;/span&gt; &lt;span style="color: brown;"&gt;&lt;b&gt;unless&lt;/b&gt;&lt;/span&gt; &lt;span style="color: darkcyan;"&gt;@result&lt;/span&gt;;&lt;br /&gt;&lt;span style="color: brown;"&gt;29 &lt;/span&gt;    &lt;span style="color: brown;"&gt;&lt;b&gt;return&lt;/b&gt;&lt;/span&gt; &lt;span style="color: brown;"&gt;&lt;b&gt;unless&lt;/b&gt;&lt;/span&gt; &lt;span style="color: darkcyan;"&gt;@result&lt;/span&gt; &amp;gt; &lt;span style="color: magenta;"&gt;1&lt;/span&gt; &lt;span style="color: brown;"&gt;&lt;b&gt;or&lt;/b&gt;&lt;/span&gt; (&lt;span style="color: brown;"&gt;&lt;b&gt;defined&lt;/b&gt;&lt;/span&gt; &lt;span style="color: darkcyan;"&gt;$result[&lt;/span&gt;&lt;span style="color: magenta;"&gt;0&lt;/span&gt;&lt;span style="color: darkcyan;"&gt;]&lt;/span&gt; &lt;span style="color: brown;"&gt;&lt;b&gt;and&lt;/b&gt;&lt;/span&gt; &lt;span style="color: darkcyan;"&gt;$result[&lt;/span&gt;&lt;span style="color: magenta;"&gt;0&lt;/span&gt;&lt;span style="color: darkcyan;"&gt;]&lt;/span&gt; &lt;span style="color: brown;"&gt;&lt;b&gt;ne&lt;/b&gt;&lt;/span&gt; &lt;span style="color: magenta;"&gt;""&lt;/span&gt;);&lt;br /&gt;&lt;span style="color: brown;"&gt;30 &lt;/span&gt;    say YAML::Dump( &lt;span style="color: darkcyan;"&gt;@result&lt;/span&gt; == &lt;span style="color: magenta;"&gt;1&lt;/span&gt; ? &lt;span style="color: darkcyan;"&gt;$result[&lt;/span&gt;&lt;span style="color: magenta;"&gt;0&lt;/span&gt;&lt;span style="color: darkcyan;"&gt;]&lt;/span&gt; : &lt;span style="color: darkcyan;"&gt;\@result&lt;/span&gt; );&lt;br /&gt;&lt;span style="color: brown;"&gt;31 &lt;/span&gt;}&lt;br /&gt;&lt;span style="color: brown;"&gt;32 &lt;/span&gt;&lt;br /&gt;&lt;span style="color: brown;"&gt;33 &lt;/span&gt;&lt;span style="color: brown;"&gt;&lt;b&gt;while&lt;/b&gt;&lt;/span&gt; ( &lt;span style="color: brown;"&gt;&lt;b&gt;defined&lt;/b&gt;&lt;/span&gt;( &lt;span style="color: brown;"&gt;&lt;b&gt;my&lt;/b&gt;&lt;/span&gt; &lt;span style="color: darkcyan;"&gt;$command&lt;/span&gt; = &lt;span style="color: darkcyan;"&gt;$term&lt;/span&gt;&lt;span style="color: darkcyan;"&gt;-&amp;gt;readline&lt;/span&gt;(&lt;span style="color: magenta;"&gt;"&lt;/span&gt;&lt;span style="color: magenta;"&gt;Listo&amp;gt; &lt;/span&gt;&lt;span style="color: magenta;"&gt;"&lt;/span&gt;) ) ) {&lt;br /&gt;&lt;span style="color: brown;"&gt;34 &lt;/span&gt;    &lt;span style="color: darkcyan;"&gt;$command&lt;/span&gt; =~ &lt;span style="color: brown;"&gt;&lt;b&gt;s/&lt;/b&gt;&lt;/span&gt;&lt;span style="color: magenta;"&gt;^&lt;/span&gt;&lt;span style="color: slateblue;"&gt;\s&lt;/span&gt;&lt;span style="color: slateblue;"&gt;+&lt;/span&gt;&lt;span style="color: brown;"&gt;&lt;b&gt;//&lt;/b&gt;&lt;/span&gt;; &lt;span style="color: darkcyan;"&gt;$command&lt;/span&gt; =~ &lt;span style="color: brown;"&gt;&lt;b&gt;s/&lt;/b&gt;&lt;/span&gt;&lt;span style="color: slateblue;"&gt;\s&lt;/span&gt;&lt;span style="color: slateblue;"&gt;+&lt;/span&gt;&lt;span style="color: magenta;"&gt;$&lt;/span&gt;&lt;span style="color: brown;"&gt;&lt;b&gt;//&lt;/b&gt;&lt;/span&gt;;&lt;br /&gt;&lt;span style="color: brown;"&gt;35 &lt;/span&gt;    &lt;span style="color: brown;"&gt;&lt;b&gt;my&lt;/b&gt;&lt;/span&gt; &lt;span style="color: darkcyan;"&gt;@args&lt;/span&gt; = &lt;span style="color: brown;"&gt;&lt;b&gt;split&lt;/b&gt;&lt;/span&gt;( &lt;span style="color: brown;"&gt;&lt;b&gt;/&lt;/b&gt;&lt;/span&gt;&lt;span style="color: slateblue;"&gt;\s&lt;/span&gt;&lt;span style="color: slateblue;"&gt;+&lt;/span&gt;&lt;span style="color: brown;"&gt;&lt;b&gt;/&lt;/b&gt;&lt;/span&gt;, &lt;span style="color: darkcyan;"&gt;$command&lt;/span&gt; ) &lt;span style="color: brown;"&gt;&lt;b&gt;or&lt;/b&gt;&lt;/span&gt; &lt;span style="color: brown;"&gt;&lt;b&gt;next&lt;/b&gt;&lt;/span&gt;;&lt;br /&gt;&lt;span style="color: brown;"&gt;36 &lt;/span&gt;    &lt;span style="color: brown;"&gt;&lt;b&gt;my&lt;/b&gt;&lt;/span&gt; &lt;span style="color: darkcyan;"&gt;$oper&lt;/span&gt; = looks_like_number( &lt;span style="color: darkcyan;"&gt;$args[&lt;/span&gt;&lt;span style="color: magenta;"&gt;0&lt;/span&gt;&lt;span style="color: darkcyan;"&gt;]&lt;/span&gt; ) ? &lt;span style="color: magenta;"&gt;"&lt;/span&gt;&lt;span style="color: magenta;"&gt;add_data&lt;/span&gt;&lt;span style="color: magenta;"&gt;"&lt;/span&gt; : &lt;span style="color: brown;"&gt;&lt;b&gt;shift&lt;/b&gt;&lt;/span&gt; &lt;span style="color: darkcyan;"&gt;@args&lt;/span&gt;;&lt;br /&gt;&lt;span style="color: brown;"&gt;37 &lt;/span&gt;    given (&lt;span style="color: darkcyan;"&gt;$oper&lt;/span&gt;) {&lt;br /&gt;&lt;span style="color: brown;"&gt;38 &lt;/span&gt;        when (&lt;span style="color: darkcyan;"&gt;%FUNCS&lt;/span&gt;)               { apply( &lt;span style="color: darkcyan;"&gt;$oper&lt;/span&gt;, &lt;span style="color: darkcyan;"&gt;@args&lt;/span&gt; ) }&lt;br /&gt;&lt;span style="color: brown;"&gt;39 &lt;/span&gt;        when (&lt;span style="color: magenta;"&gt;"&lt;/span&gt;&lt;span style="color: magenta;"&gt;man&lt;/span&gt;&lt;span style="color: magenta;"&gt;"&lt;/span&gt;)                { man &lt;span style="color: magenta;"&gt;"&lt;/span&gt;&lt;span style="color: magenta;"&gt;Statistics::Descriptive&lt;/span&gt;&lt;span style="color: magenta;"&gt;"&lt;/span&gt; }&lt;br /&gt;&lt;span style="color: brown;"&gt;40 &lt;/span&gt;        when ( [ &lt;span style="color: magenta;"&gt;"&lt;/span&gt;&lt;span style="color: magenta;"&gt;exit&lt;/span&gt;&lt;span style="color: magenta;"&gt;"&lt;/span&gt;, &lt;span style="color: magenta;"&gt;"&lt;/span&gt;&lt;span style="color: magenta;"&gt;quit&lt;/span&gt;&lt;span style="color: magenta;"&gt;"&lt;/span&gt; ] ) {&lt;span style="color: brown;"&gt;&lt;b&gt;last&lt;/b&gt;&lt;/span&gt;}&lt;br /&gt;&lt;span style="color: brown;"&gt;41 &lt;/span&gt;        when (&lt;span style="color: magenta;"&gt;"&lt;/span&gt;&lt;span style="color: magenta;"&gt;help&lt;/span&gt;&lt;span style="color: magenta;"&gt;"&lt;/span&gt;)               {help}&lt;br /&gt;&lt;span style="color: brown;"&gt;42 &lt;/span&gt;        default                     { say &lt;span style="color: magenta;"&gt;"&lt;/span&gt;&lt;span style="color: magenta;"&gt;Error: tipee 'help' para ayuda&lt;/span&gt;&lt;span style="color: magenta;"&gt;"&lt;/span&gt; };&lt;br /&gt;&lt;span style="color: brown;"&gt;43 &lt;/span&gt;    }&lt;br /&gt;&lt;span style="color: brown;"&gt;44 &lt;/span&gt;}&lt;br /&gt;&lt;/pre&gt;Después de está serie de artículos, espero que puedas apreciar, lo rápido que se puede trabajar en Perl, usando los mecanismos que ofrece el lenguaje y la inmensa cantidad de herramientas disponibles en el CPAN.&lt;br /&gt;En futuras ocasiones utilizaré este ejemplo para ilustrar otras técnicas como la programación web, la orientación a objetos de Perl y por supuesto más módulos del CPAN.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5238463735728501931-778355072149523081?l=perliscopio.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://perliscopio.blogspot.com/feeds/778355072149523081/comments/default' title='Enviar comentarios'/><link rel='replies' type='text/html' href='http://perliscopio.blogspot.com/2009/10/calculadora-estadistica-toques-finales.html#comment-form' title='0 comentarios'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5238463735728501931/posts/default/778355072149523081'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5238463735728501931/posts/default/778355072149523081'/><link rel='alternate' type='text/html' href='http://perliscopio.blogspot.com/2009/10/calculadora-estadistica-toques-finales.html' title='Calculadora Estadística: Toques finales'/><author><name>Jose Rey</name><uri>http://www.blogger.com/profile/15071755167581242815</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5238463735728501931.post-699867431502715656</id><published>2009-09-27T18:29:00.001-04:30</published><updated>2009-09-27T18:30:40.833-04:30</updated><category scheme='http://www.blogger.com/atom/ns#' term='Tutorial'/><category scheme='http://www.blogger.com/atom/ns#' term='Perl'/><category scheme='http://www.blogger.com/atom/ns#' term='CPAN'/><category scheme='http://www.blogger.com/atom/ns#' term='Programación'/><title type='text'>Calculadora Estadística: Consola Amigable</title><content type='html'>[&lt;a href="http://perliscope.blogspot.com/2009/09/statistic-calculator-user-friendly.html"&gt;English translation&lt;/a&gt;]&lt;br /&gt;Una de las características que hacen agradable el uso de una aplicación de consola es la capacidad de editar la linea de comandos y de reutilizar los comandos anteriores, estas dos características hacen la aplicación mucho más amigable.&amp;nbsp; Así que vamos a agregarlas a la &lt;a href="http://perliscopio.blogspot.com/2009/09/calculadora-estadistica-usando-el.html"&gt;calculadora del artículo anterior&lt;/a&gt;.&lt;br /&gt;Este es uno de esos trabajos donde el CPAN demuestra porque es la mejor ventaja de Perl, voy a usar &lt;a href="http://search.cpan.org/perldoc?Term%3A%3AReadLine"&gt;&lt;code&gt;Term::ReadLine&lt;/code&gt;&lt;/a&gt;, una interfaz unificada para lectura de consola, esta librería permite el uso de varios backends que son los que implementan la funcionalidad, y para que nuestro ejemplo funcione yo instalé &lt;code&gt;Term::ReadLine::Perl&lt;/code&gt;, aunque supongo que &lt;code&gt;Term::ReadLine::Gnu&lt;/code&gt; debería funcionar igual. Ambas son interfaces de la librería &lt;a href="http://linux.die.net/man/3/readline"&gt;readline(3)&lt;/a&gt; que usan muchas aplicaciones, incluyendo bash.&lt;br /&gt;Para tener una interfaz similar a la de bash solo tenemos que cambiar las líneas 27 y 28 de nuestro programa anterior por:&lt;br /&gt;&lt;pre&gt;&lt;span style="color: brown;"&gt;&lt;/span&gt;&lt;span style="color: brown;"&gt;28 &lt;/span&gt;    &lt;span style="color: brown;"&gt;&lt;b&gt;my&lt;/b&gt;&lt;/span&gt; &lt;span style="color: darkcyan;"&gt;$command&lt;/span&gt; = &lt;span style="color: darkcyan;"&gt;$term&lt;/span&gt;&lt;span style="color: darkcyan;"&gt;-&amp;gt;readline&lt;/span&gt;(&lt;span style="color: magenta;"&gt;"&lt;/span&gt;&lt;span style="color: magenta;"&gt;Listo&amp;gt; &lt;/span&gt;&lt;span style="color: magenta;"&gt;"&lt;/span&gt;) &lt;span style="color: brown;"&gt;&lt;b&gt;//&lt;/b&gt;&lt;/span&gt; &lt;span style="color: brown;"&gt;&lt;b&gt;last&lt;/b&gt;&lt;/span&gt;;&lt;span style="color: brown;"&gt;&lt;/span&gt;&lt;br /&gt;&lt;/pre&gt;como siempre, se debe declarar el uso del módulo, e inicializar el terminal creando un objeto $term que usaremos para invocar el método readline:&lt;br /&gt;&lt;pre&gt;&lt;span style="color: brown;"&gt; 7 &lt;/span&gt;&lt;span style="color: #a020f0;"&gt;use &lt;/span&gt;Term::ReadLine;&lt;br /&gt;&lt;span style="color: brown;"&gt; 8 &lt;/span&gt;&lt;br /&gt;&lt;span style="color: brown;"&gt; 9 &lt;/span&gt;&lt;span style="color: brown;"&gt;&lt;b&gt;my&lt;/b&gt;&lt;/span&gt; &lt;span style="color: darkcyan;"&gt;$term&lt;/span&gt; = &lt;span style="color: brown;"&gt;&lt;b&gt;new&lt;/b&gt;&lt;/span&gt; Term::ReadLine &lt;span style="color: magenta;"&gt;'&lt;/span&gt;&lt;span style="color: magenta;"&gt;Statistic Calculator&lt;/span&gt;&lt;span style="color: magenta;"&gt;'&lt;/span&gt;;&lt;br /&gt;&lt;/pre&gt;usamos &lt;code&gt;Term::ReadLine&lt;/code&gt; y no alguna de las variantes específicas, porque este se encarga de ejecutar las versiones específicas de manera automática, aunque permite también que el usuario mantenga control en caso de ser necesario. La librería tiene funciones que permiten adornar el prompt, autocompletar y algunas otras cosas, de nuevo el CPAN salva el día sin hacer más que leer la documentación de un módulo.&lt;br /&gt;Voy a aprovechar para reparar algunas otras cosillas que andan molestando por allí (léase bugs), primero el más fastidioso y fácil de resolver: cuando damos un comando vacío sale un mensaje de error, porque una línea vacía no es capturada por ninguna clausula when, así que el remedio es fácil, agregamos:&lt;br /&gt;&lt;pre&gt;when (&lt;span style="color: magenta;"&gt;"&lt;/span&gt;&lt;span style="color: magenta;"&gt;&lt;/span&gt;&lt;span style="color: magenta;"&gt;"&lt;/span&gt;)  {  } # si el comando es vacío no hacer nada&lt;/pre&gt;y listo.&lt;br /&gt;Otro problema más difícil de resolver son los comandos que no devuelven nada, como "clear", que nos dan un advertencia, gracias al use warnings implícito en &lt;a href="http://search.cpan.org/perldoc?Modern::Perl"&gt;Modern::Perl&lt;/a&gt;:&lt;br /&gt;&lt;pre&gt;Listo&amp;gt; clear&lt;br /&gt;Use of uninitialized value in concatenation (.) or string at calc1.pl line 32.&lt;br /&gt;clear =&lt;br /&gt;&lt;/pre&gt;Para resolver este problema voy a crear una subrutina que aplique las funciones e imprima el resultado, para mantener el ciclo de despacho lo más claro posible, así que:&lt;br /&gt;&lt;pre&gt;&lt;span style="color: brown;"&gt;32 &lt;/span&gt;  when (&lt;span style="color: darkcyan;"&gt;%FUNCS&lt;/span&gt;)  { say &lt;span style="color: magenta;"&gt;"&lt;/span&gt;&lt;span style="color: darkcyan;"&gt;$command&lt;/span&gt;&lt;span style="color: magenta;"&gt; = &lt;/span&gt;&lt;span style="color: magenta;"&gt;"&lt;/span&gt; . &lt;span style="color: darkcyan;"&gt;$s&lt;/span&gt;-&amp;gt;&lt;span style="color: darkcyan;"&gt;$command&lt;/span&gt; }&lt;/pre&gt;pasará a ser esto: &lt;br /&gt;&lt;pre&gt;&lt;span style="color: brown;"&gt;32 &lt;/span&gt;  when (&lt;span style="color: darkcyan;"&gt;%FUNCS&lt;/span&gt;)  { apply &lt;span style="color: magenta;"&gt;&lt;/span&gt;&lt;span style="color: darkcyan;"&gt;$command&lt;/span&gt;&lt;span style="color: magenta;"&gt;&lt;/span&gt; }&lt;/pre&gt;y luego implementaremos la subrutina apply, que recibe un comando, lo ejecuta y captura el resultado, pero se retorna a menos que el resultado esté definido y no sea una cadena vacia:&lt;br /&gt;&lt;pre&gt;&lt;span style="color: brown;"&gt;26 &lt;/span&gt;    &lt;span style="color: brown;"&gt;&lt;b&gt;return&lt;/b&gt;&lt;/span&gt; &lt;span style="color: brown;"&gt;&lt;b&gt;unless&lt;/b&gt;&lt;/span&gt; &lt;span style="color: brown;"&gt;&lt;b&gt;defined&lt;/b&gt;&lt;/span&gt; &lt;span style="color: darkcyan;"&gt;$result&lt;/span&gt; &lt;span style="color: brown;"&gt;&lt;b&gt;and&lt;/b&gt;&lt;/span&gt; &lt;span style="color: darkcyan;"&gt;$result&lt;/span&gt; &lt;span style="color: brown;"&gt;&lt;b&gt;ne&lt;/b&gt;&lt;/span&gt; &lt;span style="color: magenta;"&gt;""&lt;/span&gt;;&lt;br /&gt;&lt;/pre&gt;La calculadora ahora esvmás amigable, sin embargo todavía tiene problemas, si ejecutan trimmed_mean se darán cuenta de que da un error, en el manual está la causa, la función trimmed_mean recibe 1 o 2 parámetros, pero por ahora la calculadora solo acepta comandos sin parámetros, en el próximo artículo veremos como agregarle parámetros y también desplegar resultados no escalares, como arreglos y hashes.&lt;br /&gt;Nuestro programa completo ahora luce así:&lt;br /&gt;&lt;pre&gt;&lt;span style="color: brown;"&gt; 1 &lt;/span&gt;&lt;span style="color: #a020f0;"&gt;#!/usr/bin/perl&lt;/span&gt;&lt;br /&gt;&lt;span style="color: brown;"&gt; 2 &lt;/span&gt;&lt;br /&gt;&lt;span style="color: brown;"&gt; 3 &lt;/span&gt;&lt;span style="color: #a020f0;"&gt;use &lt;/span&gt;Modern::Perl;&lt;br /&gt;&lt;span style="color: brown;"&gt; 4 &lt;/span&gt;&lt;span style="color: #a020f0;"&gt;use &lt;/span&gt;Scalar::Util &lt;span style="color: magenta;"&gt;qw(&lt;/span&gt;&lt;span style="color: magenta;"&gt; looks_like_number &lt;/span&gt;&lt;span style="color: magenta;"&gt;)&lt;/span&gt;;&lt;br /&gt;&lt;span style="color: brown;"&gt; 5 &lt;/span&gt;&lt;span style="color: #a020f0;"&gt;use &lt;/span&gt;Statistics::Descriptive;&lt;br /&gt;&lt;span style="color: brown;"&gt; 6 &lt;/span&gt;&lt;span style="color: #a020f0;"&gt;use &lt;/span&gt;Pod::Perldoc;&lt;br /&gt;&lt;span style="color: brown;"&gt; 7 &lt;/span&gt;&lt;span style="color: #a020f0;"&gt;use &lt;/span&gt;Term::ReadLine;&lt;br /&gt;&lt;span style="color: brown;"&gt; 8 &lt;/span&gt;&lt;br /&gt;&lt;span style="color: brown;"&gt; 9 &lt;/span&gt;&lt;span style="color: brown;"&gt;&lt;b&gt;my&lt;/b&gt;&lt;/span&gt; &lt;span style="color: darkcyan;"&gt;$term&lt;/span&gt; = &lt;span style="color: brown;"&gt;&lt;b&gt;new&lt;/b&gt;&lt;/span&gt; Term::ReadLine &lt;span style="color: magenta;"&gt;'&lt;/span&gt;&lt;span style="color: magenta;"&gt;Statistic Calculator&lt;/span&gt;&lt;span style="color: magenta;"&gt;'&lt;/span&gt;;&lt;br /&gt;&lt;span style="color: brown;"&gt;10 &lt;/span&gt;&lt;br /&gt;&lt;span style="color: brown;"&gt;11 &lt;/span&gt;&lt;span style="color: brown;"&gt;&lt;b&gt;my&lt;/b&gt;&lt;/span&gt; &lt;span style="color: darkcyan;"&gt;%FUNCS&lt;/span&gt; = &lt;span style="color: brown;"&gt;&lt;b&gt;map&lt;/b&gt;&lt;/span&gt; { &lt;span style="color: darkcyan;"&gt;$_&lt;/span&gt; =&amp;gt; &lt;span style="color: magenta;"&gt;1&lt;/span&gt; } &lt;span style="color: magenta;"&gt;qw(&lt;/span&gt;&lt;span style="color: magenta;"&gt; sum mean count variance standard_deviation&lt;/span&gt;&lt;br /&gt;&lt;span style="color: brown;"&gt;12 &lt;/span&gt;&lt;span style="color: magenta;"&gt;    min mindex max maxdex sample_range median harmonic_mean geometric_mean&lt;/span&gt;&lt;br /&gt;&lt;span style="color: brown;"&gt;13 &lt;/span&gt;&lt;span style="color: magenta;"&gt;    mode trimmed_mean clear &lt;/span&gt;&lt;span style="color: magenta;"&gt;)&lt;/span&gt;;&lt;br /&gt;&lt;span style="color: brown;"&gt;14 &lt;/span&gt;&lt;br /&gt;&lt;span style="color: brown;"&gt;15 &lt;/span&gt;&lt;span style="color: brown;"&gt;&lt;b&gt;my&lt;/b&gt;&lt;/span&gt; &lt;span style="color: darkcyan;"&gt;@COMMANDS&lt;/span&gt; = &lt;span style="color: magenta;"&gt;qw(&lt;/span&gt;&lt;span style="color: magenta;"&gt; exit quit help man &lt;/span&gt;&lt;span style="color: magenta;"&gt;)&lt;/span&gt;;&lt;br /&gt;&lt;span style="color: brown;"&gt;16 &lt;/span&gt;&lt;br /&gt;&lt;span style="color: brown;"&gt;17 &lt;/span&gt;&lt;span style="color: brown;"&gt;&lt;b&gt;sub&lt;/b&gt;&lt;/span&gt;&lt;span style="color: darkcyan;"&gt; &lt;/span&gt;&lt;span style="color: darkcyan;"&gt;help &lt;/span&gt;{ say &lt;span style="color: magenta;"&gt;"&lt;/span&gt;&lt;span style="color: magenta;"&gt;Comandos: &lt;/span&gt;&lt;span style="color: magenta;"&gt;"&lt;/span&gt; . &lt;span style="color: brown;"&gt;&lt;b&gt;join&lt;/b&gt;&lt;/span&gt;( &lt;span style="color: magenta;"&gt;"&lt;/span&gt;&lt;span style="color: magenta;"&gt;, &lt;/span&gt;&lt;span style="color: magenta;"&gt;"&lt;/span&gt;, &lt;span style="color: brown;"&gt;&lt;b&gt;sort&lt;/b&gt;&lt;/span&gt; &lt;span style="color: darkcyan;"&gt;@COMMANDS&lt;/span&gt;, &lt;span style="color: brown;"&gt;&lt;b&gt;keys&lt;/b&gt;&lt;/span&gt; &lt;span style="color: darkcyan;"&gt;%FUNCS&lt;/span&gt; ) }&lt;br /&gt;&lt;span style="color: brown;"&gt;18 &lt;/span&gt;&lt;br /&gt;&lt;span style="color: brown;"&gt;19 &lt;/span&gt;&lt;span style="color: brown;"&gt;&lt;b&gt;sub&lt;/b&gt;&lt;/span&gt;&lt;span style="color: darkcyan;"&gt; &lt;/span&gt;&lt;span style="color: darkcyan;"&gt;man &lt;/span&gt;{ Pod::Perldoc-&amp;gt;&lt;span style="color: brown;"&gt;&lt;b&gt;new&lt;/b&gt;&lt;/span&gt;(&lt;span style="color: magenta;"&gt;args &lt;/span&gt;=&amp;gt; &lt;span style="color: darkcyan;"&gt;\@_&lt;/span&gt;)-&amp;gt;process }&lt;br /&gt;&lt;span style="color: brown;"&gt;20 &lt;/span&gt;&lt;br /&gt;&lt;span style="color: brown;"&gt;21 &lt;/span&gt;&lt;span style="color: brown;"&gt;&lt;b&gt;my&lt;/b&gt;&lt;/span&gt; &lt;span style="color: darkcyan;"&gt;$s&lt;/span&gt; = Statistics::Descriptive::Full-&amp;gt;&lt;span style="color: brown;"&gt;&lt;b&gt;new&lt;/b&gt;&lt;/span&gt;();&lt;br /&gt;&lt;span style="color: brown;"&gt;22 &lt;/span&gt;&lt;br /&gt;&lt;span style="color: brown;"&gt;23 &lt;/span&gt;&lt;span style="color: brown;"&gt;&lt;b&gt;sub&lt;/b&gt;&lt;/span&gt;&lt;span style="color: darkcyan;"&gt; &lt;/span&gt;&lt;span style="color: darkcyan;"&gt;apply &lt;/span&gt;{&lt;br /&gt;&lt;span style="color: brown;"&gt;24 &lt;/span&gt;    &lt;span style="color: brown;"&gt;&lt;b&gt;my&lt;/b&gt;&lt;/span&gt; &lt;span style="color: darkcyan;"&gt;$command&lt;/span&gt; = &lt;span style="color: brown;"&gt;&lt;b&gt;shift&lt;/b&gt;&lt;/span&gt;;&lt;br /&gt;&lt;span style="color: brown;"&gt;25 &lt;/span&gt;    &lt;span style="color: brown;"&gt;&lt;b&gt;my&lt;/b&gt;&lt;/span&gt; &lt;span style="color: darkcyan;"&gt;$result&lt;/span&gt; = &lt;span style="color: darkcyan;"&gt;$s&lt;/span&gt;-&amp;gt;&lt;span style="color: darkcyan;"&gt;$command&lt;/span&gt;;&lt;br /&gt;&lt;span style="color: brown;"&gt;26 &lt;/span&gt;    &lt;span style="color: brown;"&gt;&lt;b&gt;return&lt;/b&gt;&lt;/span&gt; &lt;span style="color: brown;"&gt;&lt;b&gt;unless&lt;/b&gt;&lt;/span&gt; &lt;span style="color: brown;"&gt;&lt;b&gt;defined&lt;/b&gt;&lt;/span&gt; &lt;span style="color: darkcyan;"&gt;$result&lt;/span&gt; &lt;span style="color: brown;"&gt;&lt;b&gt;and&lt;/b&gt;&lt;/span&gt; &lt;span style="color: darkcyan;"&gt;$result&lt;/span&gt; &lt;span style="color: brown;"&gt;&lt;b&gt;ne&lt;/b&gt;&lt;/span&gt; &lt;span style="color: magenta;"&gt;""&lt;/span&gt;;&lt;br /&gt;&lt;span style="color: brown;"&gt;27 &lt;/span&gt;    say &lt;span style="color: magenta;"&gt;"&lt;/span&gt;&lt;span style="color: darkcyan;"&gt;$command&lt;/span&gt;&lt;span style="color: magenta;"&gt; = &lt;/span&gt;&lt;span style="color: darkcyan;"&gt;$result&lt;/span&gt;&lt;span style="color: magenta;"&gt;"&lt;/span&gt;;&lt;br /&gt;&lt;span style="color: brown;"&gt;28 &lt;/span&gt;}&lt;br /&gt;&lt;span style="color: brown;"&gt;29 &lt;/span&gt;&lt;br /&gt;&lt;span style="color: brown;"&gt;30 &lt;/span&gt;&lt;span style="color: brown;"&gt;&lt;b&gt;while&lt;/b&gt;&lt;/span&gt; (&lt;span style="color: brown;"&gt;&lt;b&gt;defined&lt;/b&gt;&lt;/span&gt;(&lt;span style="color: brown;"&gt;&lt;b&gt;my&lt;/b&gt;&lt;/span&gt; &lt;span style="color: darkcyan;"&gt;$command&lt;/span&gt; = &lt;span style="color: darkcyan;"&gt;$term&lt;/span&gt;&lt;span style="color: darkcyan;"&gt;-&amp;gt;readline&lt;/span&gt;(&lt;span style="color: magenta;"&gt;"&lt;/span&gt;&lt;span style="color: magenta;"&gt;Listo&amp;gt; &lt;/span&gt;&lt;span style="color: magenta;"&gt;"&lt;/span&gt;))) {&lt;br /&gt;&lt;span style="color: brown;"&gt;31 &lt;/span&gt;    &lt;span style="color: darkcyan;"&gt;$command&lt;/span&gt; =~ &lt;span style="color: brown;"&gt;&lt;b&gt;s/&lt;/b&gt;&lt;/span&gt;&lt;span style="color: magenta;"&gt;^&lt;/span&gt;&lt;span style="color: slateblue;"&gt;\s&lt;/span&gt;&lt;span style="color: slateblue;"&gt;+&lt;/span&gt;&lt;span style="color: brown;"&gt;&lt;b&gt;//&lt;/b&gt;&lt;/span&gt;; &lt;span style="color: darkcyan;"&gt;$command&lt;/span&gt; =~ &lt;span style="color: brown;"&gt;&lt;b&gt;s/&lt;/b&gt;&lt;/span&gt;&lt;span style="color: slateblue;"&gt;\s&lt;/span&gt;&lt;span style="color: slateblue;"&gt;+&lt;/span&gt;&lt;span style="color: magenta;"&gt;$&lt;/span&gt;&lt;span style="color: brown;"&gt;&lt;b&gt;//&lt;/b&gt;&lt;/span&gt;;&lt;br /&gt;&lt;span style="color: brown;"&gt;32 &lt;/span&gt;    given (&lt;span style="color: darkcyan;"&gt;$command&lt;/span&gt;) {&lt;br /&gt;&lt;span style="color: brown;"&gt;33 &lt;/span&gt;        when ( looks_like_number(&lt;span style="color: darkcyan;"&gt;$_&lt;/span&gt;) ) { &lt;span style="color: darkcyan;"&gt;$s&lt;/span&gt;&lt;span style="color: darkcyan;"&gt;-&amp;gt;add_data&lt;/span&gt;(&lt;span style="color: darkcyan;"&gt;$command&lt;/span&gt;) }&lt;br /&gt;&lt;span style="color: brown;"&gt;34 &lt;/span&gt;        when (&lt;span style="color: darkcyan;"&gt;%FUNCS&lt;/span&gt;)                  { apply &lt;span style="color: darkcyan;"&gt;$command&lt;/span&gt; }&lt;br /&gt;&lt;span style="color: brown;"&gt;35 &lt;/span&gt;        when (&lt;span style="color: magenta;"&gt;"&lt;/span&gt;&lt;span style="color: magenta;"&gt;man&lt;/span&gt;&lt;span style="color: magenta;"&gt;"&lt;/span&gt;)                   { man &lt;span style="color: magenta;"&gt;"&lt;/span&gt;&lt;span style="color: magenta;"&gt;Statistics::Descriptive&lt;/span&gt;&lt;span style="color: magenta;"&gt;"&lt;/span&gt; }&lt;br /&gt;&lt;span style="color: brown;"&gt;36 &lt;/span&gt;        when ( [ &lt;span style="color: magenta;"&gt;"&lt;/span&gt;&lt;span style="color: magenta;"&gt;exit&lt;/span&gt;&lt;span style="color: magenta;"&gt;"&lt;/span&gt;, &lt;span style="color: magenta;"&gt;"&lt;/span&gt;&lt;span style="color: magenta;"&gt;quit&lt;/span&gt;&lt;span style="color: magenta;"&gt;"&lt;/span&gt; ] )    { &lt;span style="color: brown;"&gt;&lt;b&gt;last&lt;/b&gt;&lt;/span&gt; }&lt;br /&gt;&lt;span style="color: brown;"&gt;37 &lt;/span&gt;        when (&lt;span style="color: magenta;"&gt;"&lt;/span&gt;&lt;span style="color: magenta;"&gt;help&lt;/span&gt;&lt;span style="color: magenta;"&gt;"&lt;/span&gt;)                  { help }&lt;br /&gt;&lt;span style="color: brown;"&gt;38 &lt;/span&gt;        when (&lt;span style="color: magenta;"&gt;""&lt;/span&gt;)                      { }&lt;br /&gt;&lt;span style="color: brown;"&gt;39 &lt;/span&gt;        default                        { say &lt;span style="color: magenta;"&gt;"&lt;/span&gt;&lt;span style="color: magenta;"&gt;Error: tipee 'help' para ayuda&lt;/span&gt;&lt;span style="color: magenta;"&gt;"&lt;/span&gt; }&lt;br /&gt;&lt;span style="color: brown;"&gt;40 &lt;/span&gt;    }&lt;br /&gt;&lt;span style="color: brown;"&gt;41 &lt;/span&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5238463735728501931-699867431502715656?l=perliscopio.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://perliscopio.blogspot.com/feeds/699867431502715656/comments/default' title='Enviar comentarios'/><link rel='replies' type='text/html' href='http://perliscopio.blogspot.com/2009/09/calculadora-estadistica-consola.html#comment-form' title='0 comentarios'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5238463735728501931/posts/default/699867431502715656'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5238463735728501931/posts/default/699867431502715656'/><link rel='alternate' type='text/html' href='http://perliscopio.blogspot.com/2009/09/calculadora-estadistica-consola.html' title='Calculadora Estadística: Consola Amigable'/><author><name>Jose Rey</name><uri>http://www.blogger.com/profile/15071755167581242815</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5238463735728501931.post-5705454436703813678</id><published>2009-09-23T10:10:00.006-04:30</published><updated>2009-09-27T18:32:16.971-04:30</updated><category scheme='http://www.blogger.com/atom/ns#' term='Tutorial'/><category scheme='http://www.blogger.com/atom/ns#' term='Perl'/><category scheme='http://www.blogger.com/atom/ns#' term='Programación'/><title type='text'>Calculadora Estadística: Usando el sistema</title><content type='html'>[&lt;a href="http://perliscope.blogspot.com/2009/09/statistic-calculator-using-system.html"&gt;English translation&lt;/a&gt;]&lt;br /&gt;En el &lt;a href="http://perliscopio.blogspot.com/2009/09/perl-inteligente.html"&gt;artículo anterior&lt;/a&gt; dejamos pendiente agregar un manual a nuestra calculadora, veamos algunas maneras de interactuar con el sistema de documentación en Perl para lograrlo.&lt;br /&gt;El comando para ver la documentación en la calculadora sera "man" y como asumo que la mayoría debe haber interactuado con &lt;a href="http://perldoc.perl.org/perldoc.html"&gt;perldoc&lt;/a&gt;, voy a comenzar utilizando directamente este comando para mostrar un manual.&lt;br /&gt;Perl desde hace mucho tiene la capacidad de ejecutar comandos del sistema de varias formas, una de ellas es el operador "`", si escribimos algo como:&lt;br /&gt;&lt;pre&gt;&lt;span style="color: brown;"&gt;1  &lt;/span&gt;&lt;span style="color: brown;"&gt;&lt;b&gt;my&lt;/b&gt;&lt;/span&gt; &lt;span style="color: darkcyan;"&gt;@out&lt;/span&gt; = &lt;span style="color: brown;"&gt;&lt;b&gt;`&lt;/b&gt;&lt;/span&gt;&lt;span style="color: magenta;"&gt;ls -l&lt;/span&gt;&lt;span style="color: brown;"&gt;&lt;b&gt;`&lt;/b&gt;&lt;/span&gt;&lt;br /&gt;&lt;/pre&gt;el arreglo @out terminará con cada una de las líneas de la salida del comando, también se pueden ejecutar comandos con &lt;a href="http://perldoc.perl.org/functions/open.html"&gt;open&lt;/a&gt; y utilizar su salida como entrada para un programa:&lt;br /&gt;&lt;pre&gt;&lt;span style="color: brown;"&gt;1 &lt;/span&gt;&lt;span style="color: brown;"&gt;&lt;b&gt;open&lt;/b&gt;&lt;/span&gt; &lt;span style="color: darkcyan;"&gt;$fd&lt;/span&gt;, &lt;span style="color: magenta;"&gt;"&lt;/span&gt;&lt;span style="color: magenta;"&gt;-|&lt;/span&gt;&lt;span style="color: magenta;"&gt;"&lt;/span&gt;, &lt;span style="color: magenta;"&gt;"&lt;/span&gt;&lt;span style="color: magenta;"&gt;ls -ls&lt;/span&gt;&lt;span style="color: magenta;"&gt;"&lt;/span&gt; &lt;span style="color: brown;"&gt;&lt;b&gt;or&lt;/b&gt;&lt;/span&gt; &lt;span style="color: brown;"&gt;&lt;b&gt;die&lt;/b&gt;&lt;/span&gt; &lt;span style="color: magenta;"&gt;"&lt;/span&gt;&lt;span style="color: magenta;"&gt;Error: &lt;/span&gt;&lt;span style="color: darkcyan;"&gt;$!&lt;/span&gt;&lt;span style="color: magenta;"&gt;"&lt;/span&gt;&lt;br /&gt;&lt;span style="color: brown;"&gt;2 &lt;/span&gt;&lt;span style="color: brown;"&gt;&lt;b&gt;while&lt;/b&gt;&lt;/span&gt; ( &lt;span style="color: brown;"&gt;&lt;b&gt;readline&lt;/b&gt;&lt;/span&gt; &lt;span style="color: darkcyan;"&gt;$fd&lt;/span&gt; ) {&lt;br /&gt;&lt;span style="color: brown;"&gt;3 &lt;/span&gt;    &lt;span style="color: blue;"&gt;# $_ contiene una línea de la salida del comando&lt;/span&gt;&lt;br /&gt;&lt;span style="color: brown;"&gt;4 &lt;/span&gt;}&lt;br /&gt;&lt;/pre&gt;lo cual es sorprendente, aunque no muy recomendado en estos días, pero lo uso una y otra vez en el trabajo, donde arreglo montones de cosas con microprogramas en Perl.&lt;br /&gt;Sin embargo hoy estoy interesado en la función "&lt;a href="http://perldoc.perl.org/functions/system.html"&gt;system&lt;/a&gt;" que voy a usar en la primera forma de agregarle un manual a la calculadora.&lt;br /&gt;Como no quiero complicarme mostrando &lt;a href="http://perldoc.perl.org/perlpod.html"&gt;como se escribe un manual&lt;/a&gt;, por ahora usaré el manual del módulo Statistics::Descriptive, la solución es simplemente agregar una línea al programa del &lt;a href="http://perliscopio.blogspot.com/2009/09/perl-inteligente.html"&gt;artículo anterior&lt;/a&gt;:&lt;br /&gt;&lt;pre&gt;&lt;span style="color: brown;"&gt;21 &lt;/span&gt; when (&lt;span style="color: magenta;"&gt;"&lt;/span&gt;&lt;span style="color: magenta;"&gt;man&lt;/span&gt;&lt;span style="color: magenta;"&gt;"&lt;/span&gt;)  { &lt;span style="color: brown;"&gt;&lt;b&gt;system&lt;/b&gt;&lt;/span&gt;(&lt;span style="color: magenta;"&gt;"&lt;/span&gt;&lt;span style="color: magenta;"&gt;perldoc Statistics::Descriptive&lt;/span&gt;&lt;span style="color: magenta;"&gt;"&lt;/span&gt;) }&lt;br /&gt;&lt;/pre&gt;y eso eso es todo, así es Perl, no hay nada más fácil, algunos podrán decir que es sucio, pero definitivamente fue fácil. Cuando usamos "&lt;a href="http://perldoc.perl.org/functions/system.html"&gt;system&lt;/a&gt;" de esta manera perl envía el comando directamente al shell, así que es mejor usarlo así:&lt;br /&gt;&lt;pre&gt;&lt;span style="color: brown;"&gt;21 &lt;/span&gt; when (&lt;span style="color: magenta;"&gt;"&lt;/span&gt;&lt;span style="color: magenta;"&gt;man&lt;/span&gt;&lt;span style="color: magenta;"&gt;"&lt;/span&gt;)  { &lt;span style="color: brown;"&gt;&lt;b&gt;system&lt;/b&gt;&lt;/span&gt;(&lt;span style="color: magenta;"&gt;"&lt;/span&gt;&lt;span style="color: magenta;"&gt;/usr/bin/perldoc", "Statistics::Descriptive&lt;/span&gt;&lt;span style="color: magenta;"&gt;"&lt;/span&gt;) }&lt;br /&gt;&lt;/pre&gt;al pasarle a &lt;a href="http://perldoc.perl.org/functions/system.html"&gt;system&lt;/a&gt; una lista de argumentos perl ejecuta directamente el comando, evitando algunos problemillas de seguridad que podrían ocurrir, pero el comando no se busca en el PATH, así que debes pasar la ruta completa al ejecutable.&lt;br /&gt;No es una gran sorpresa que el comando perldoc está escrito en Perl, así que probablemente podemos reutilizar el código de este programa en nuestra calculadora, mirando dentro del programa te darás cuenta que perldoc es un programa muy simple, en efecto, las dos líneas importantes son:&lt;br /&gt;&lt;pre&gt;&lt;span style="color: brown;"&gt;1 &lt;/span&gt;&lt;span style="color: #a020f0;"&gt;use &lt;/span&gt;Pod::Perldoc;&lt;br /&gt;&lt;span style="color: brown;"&gt;2 &lt;/span&gt;Pod::Perldoc-&amp;gt;run();&lt;br /&gt;&lt;/pre&gt;Asi que toda la funcionalidad de perldoc está metida dentro de un objeto de Perl!, esto es un patrón importante de la cultura Perl, pues permite reutilizar fácilmente cualquier aplicación en otra, que es exactamente lo que queremos hacer, desafortunadamente alguien olvidó documentar &lt;code&gt;Pod::Perldoc&lt;/code&gt; así que me metí a ver como lo puedo integrar en mi programa, el resultado fue cambiar la línea 21:&lt;br /&gt;&lt;pre&gt;&lt;span style="color: brown;"&gt;21 &lt;/span&gt; when (&lt;span style="color: magenta;"&gt;"&lt;/span&gt;&lt;span style="color: magenta;"&gt;man&lt;/span&gt;&lt;span style="color: magenta;"&gt;"&lt;/span&gt;) { Pod::Perldoc-&amp;gt;&lt;span style="color: brown;"&gt;&lt;b&gt;new&lt;/b&gt;&lt;/span&gt;(&lt;span style="color: magenta;"&gt;args &lt;/span&gt;=&amp;gt; [&lt;span style="color: magenta;"&gt;"&lt;/span&gt;&lt;span style="color: magenta;"&gt;Statistics::Descriptive&lt;/span&gt;&lt;span style="color: magenta;"&gt;"&lt;/span&gt;])-&amp;gt;process }&lt;br /&gt;&lt;/pre&gt;y por supuesto declarar el uso de la clase al principio del programa:&lt;br /&gt;&lt;pre&gt;&lt;span style="color: brown;"&gt; 6 &lt;/span&gt;&lt;span style="color: #a020f0;"&gt;use &lt;/span&gt;Pod::Perldoc;&lt;br /&gt;&lt;/pre&gt;El único trabajo real fue aprender como funcionaba &lt;code&gt;Pod::Perldoc&lt;/code&gt; y me tomó menos de 2 minutos (usando el excelente &lt;a href="http://perldoc.perl.org/perldebug.html"&gt;depurador de perl&lt;/a&gt;).&lt;br /&gt;Finalmente me tomé el tiempo para refactorizar un poquito el programa, mejorar el comando "help" y al final que quedó así:&lt;br /&gt;&lt;pre&gt;&lt;span style="color: brown;"&gt; 1 &lt;/span&gt;&lt;span style="color: #a020f0;"&gt;#!/usr/bin/perl&lt;/span&gt;&lt;br /&gt;&lt;span style="color: brown;"&gt; 2 &lt;/span&gt;&lt;br /&gt;&lt;span style="color: brown;"&gt; 3 &lt;/span&gt;&lt;span style="color: #a020f0;"&gt;use &lt;/span&gt;Modern::Perl;&lt;br /&gt;&lt;span style="color: brown;"&gt; 4 &lt;/span&gt;&lt;span style="color: #a020f0;"&gt;use &lt;/span&gt;Scalar::Util &lt;span style="color: magenta;"&gt;qw(&lt;/span&gt;&lt;span style="color: magenta;"&gt; looks_like_number &lt;/span&gt;&lt;span style="color: magenta;"&gt;)&lt;/span&gt;;&lt;br /&gt;&lt;span style="color: brown;"&gt; 5 &lt;/span&gt;&lt;span style="color: #a020f0;"&gt;use &lt;/span&gt;Statistics::Descriptive;&lt;br /&gt;&lt;span style="color: brown;"&gt; 6 &lt;/span&gt;&lt;span style="color: #a020f0;"&gt;use &lt;/span&gt;Pod::Perldoc;&lt;br /&gt;&lt;span style="color: brown;"&gt; 7 &lt;/span&gt;&lt;br /&gt;&lt;span style="color: brown;"&gt; 8 &lt;/span&gt;&lt;span style="color: #a020f0;"&gt;use constant&lt;/span&gt; &lt;span style="color: magenta;"&gt;SYNTAX_ERROR &lt;/span&gt;=&amp;gt; &lt;span style="color: magenta;"&gt;"&lt;/span&gt;&lt;span style="color: magenta;"&gt;Error: tipee 'help' para ayuda&lt;/span&gt;&lt;span style="color: magenta;"&gt;"&lt;/span&gt;;&lt;br /&gt;&lt;span style="color: brown;"&gt; 9 &lt;/span&gt;&lt;br /&gt;&lt;span style="color: brown;"&gt;10 &lt;/span&gt;&lt;span style="color: brown;"&gt;&lt;b&gt;my&lt;/b&gt;&lt;/span&gt; &lt;span style="color: darkcyan;"&gt;%FUNCS&lt;/span&gt; = &lt;span style="color: brown;"&gt;&lt;b&gt;map&lt;/b&gt;&lt;/span&gt; { &lt;span style="color: darkcyan;"&gt;$_&lt;/span&gt; =&amp;gt; &lt;span style="color: magenta;"&gt;1&lt;/span&gt; } &lt;span style="color: magenta;"&gt;qw(&lt;/span&gt;&lt;span style="color: magenta;"&gt; sum mean count variance standard_deviation&lt;/span&gt;&lt;br /&gt;&lt;span style="color: brown;"&gt;11 &lt;/span&gt;&lt;span style="color: magenta;"&gt;    min mindex max maxdex sample_range median harmonic_mean geometric_mean&lt;/span&gt;&lt;br /&gt;&lt;span style="color: brown;"&gt;12 &lt;/span&gt;&lt;span style="color: magenta;"&gt;    mode trimmed_mean clear &lt;/span&gt;&lt;span style="color: magenta;"&gt;)&lt;/span&gt;;&lt;br /&gt;&lt;span style="color: brown;"&gt;13 &lt;/span&gt;&lt;br /&gt;&lt;span style="color: brown;"&gt;14 &lt;/span&gt;&lt;span style="color: brown;"&gt;&lt;b&gt;my&lt;/b&gt;&lt;/span&gt; &lt;span style="color: darkcyan;"&gt;@COMMANDS&lt;/span&gt; = &lt;span style="color: magenta;"&gt;qw(&lt;/span&gt;&lt;span style="color: magenta;"&gt; exit quit help man &lt;/span&gt;&lt;span style="color: magenta;"&gt;)&lt;/span&gt;;&lt;br /&gt;&lt;span style="color: brown;"&gt;15 &lt;/span&gt;&lt;br /&gt;&lt;span style="color: brown;"&gt;16 &lt;/span&gt;&lt;span style="color: brown;"&gt;&lt;b&gt;sub&lt;/b&gt;&lt;/span&gt;&lt;span style="color: darkcyan;"&gt; &lt;/span&gt;&lt;span style="color: darkcyan;"&gt;help &lt;/span&gt;{&lt;br /&gt;&lt;span style="color: brown;"&gt;17 &lt;/span&gt;    say &lt;span style="color: magenta;"&gt;"&lt;/span&gt;&lt;span style="color: magenta;"&gt;Comandos: &lt;/span&gt;&lt;span style="color: magenta;"&gt;"&lt;/span&gt; . &lt;span style="color: brown;"&gt;&lt;b&gt;join&lt;/b&gt;&lt;/span&gt;( &lt;span style="color: magenta;"&gt;"&lt;/span&gt;&lt;span style="color: magenta;"&gt;, &lt;/span&gt;&lt;span style="color: magenta;"&gt;"&lt;/span&gt;, &lt;span style="color: darkcyan;"&gt;@COMMANDS&lt;/span&gt; );&lt;br /&gt;&lt;span style="color: brown;"&gt;18 &lt;/span&gt;    say &lt;span style="color: magenta;"&gt;"&lt;/span&gt;&lt;span style="color: magenta;"&gt;Funciones: &lt;/span&gt;&lt;span style="color: magenta;"&gt;"&lt;/span&gt; . &lt;span style="color: brown;"&gt;&lt;b&gt;join&lt;/b&gt;&lt;/span&gt;( &lt;span style="color: magenta;"&gt;"&lt;/span&gt;&lt;span style="color: magenta;"&gt;, &lt;/span&gt;&lt;span style="color: magenta;"&gt;"&lt;/span&gt;, &lt;span style="color: brown;"&gt;&lt;b&gt;keys&lt;/b&gt;&lt;/span&gt; &lt;span style="color: darkcyan;"&gt;%FUNCS&lt;/span&gt; );&lt;br /&gt;&lt;span style="color: brown;"&gt;19 &lt;/span&gt;}&lt;br /&gt;&lt;span style="color: brown;"&gt;20 &lt;/span&gt;&lt;br /&gt;&lt;span style="color: brown;"&gt;21 &lt;/span&gt;&lt;span style="color: brown;"&gt;&lt;b&gt;sub&lt;/b&gt;&lt;/span&gt;&lt;span style="color: darkcyan;"&gt; &lt;/span&gt;&lt;span style="color: darkcyan;"&gt;man &lt;/span&gt;{&lt;br /&gt;&lt;span style="color: brown;"&gt;22 &lt;/span&gt;    Pod::Perldoc-&amp;gt;&lt;span style="color: brown;"&gt;&lt;b&gt;new&lt;/b&gt;&lt;/span&gt;(&lt;span style="color: magenta;"&gt;args &lt;/span&gt;=&amp;gt; &lt;span style="color: darkcyan;"&gt;\@_&lt;/span&gt;)-&amp;gt;process&lt;br /&gt;&lt;span style="color: brown;"&gt;23 &lt;/span&gt;}&lt;br /&gt;&lt;span style="color: brown;"&gt;24 &lt;/span&gt;&lt;br /&gt;&lt;span style="color: brown;"&gt;25 &lt;/span&gt;&lt;span style="color: brown;"&gt;&lt;b&gt;my&lt;/b&gt;&lt;/span&gt; &lt;span style="color: darkcyan;"&gt;$s&lt;/span&gt; = Statistics::Descriptive::Full-&amp;gt;&lt;span style="color: brown;"&gt;&lt;b&gt;new&lt;/b&gt;&lt;/span&gt;();&lt;br /&gt;&lt;span style="color: brown;"&gt;26 &lt;/span&gt;&lt;span style="color: brown;"&gt;&lt;b&gt;while&lt;/b&gt;&lt;/span&gt; (&lt;span style="color: magenta;"&gt;1&lt;/span&gt;) {&lt;br /&gt;&lt;span style="color: brown;"&gt;27 &lt;/span&gt;    &lt;span style="color: brown;"&gt;&lt;b&gt;print&lt;/b&gt;&lt;/span&gt; &lt;span style="color: magenta;"&gt;"&lt;/span&gt;&lt;span style="color: magenta;"&gt;Listo&amp;gt; &lt;/span&gt;&lt;span style="color: magenta;"&gt;"&lt;/span&gt;;&lt;br /&gt;&lt;span style="color: brown;"&gt;28 &lt;/span&gt;    &lt;span style="color: brown;"&gt;&lt;b&gt;my&lt;/b&gt;&lt;/span&gt; &lt;span style="color: darkcyan;"&gt;$command&lt;/span&gt; = &lt;span style="color: brown;"&gt;&lt;b&gt;readline&lt;/b&gt;&lt;/span&gt;(&lt;span style="color: darkcyan;"&gt;STDIN&lt;/span&gt;) &lt;span style="color: brown;"&gt;&lt;b&gt;//&lt;/b&gt;&lt;/span&gt; &lt;span style="color: brown;"&gt;&lt;b&gt;last&lt;/b&gt;&lt;/span&gt;;&lt;br /&gt;&lt;span style="color: brown;"&gt;29 &lt;/span&gt;    &lt;span style="color: darkcyan;"&gt;$command&lt;/span&gt; =~ &lt;span style="color: brown;"&gt;&lt;b&gt;s/&lt;/b&gt;&lt;/span&gt;&lt;span style="color: magenta;"&gt;^&lt;/span&gt;&lt;span style="color: slateblue;"&gt;\s&lt;/span&gt;&lt;span style="color: slateblue;"&gt;+&lt;/span&gt;&lt;span style="color: brown;"&gt;&lt;b&gt;//&lt;/b&gt;&lt;/span&gt;; &lt;span style="color: darkcyan;"&gt;$command&lt;/span&gt; =~ &lt;span style="color: brown;"&gt;&lt;b&gt;s/&lt;/b&gt;&lt;/span&gt;&lt;span style="color: slateblue;"&gt;\s&lt;/span&gt;&lt;span style="color: slateblue;"&gt;+&lt;/span&gt;&lt;span style="color: magenta;"&gt;$&lt;/span&gt;&lt;span style="color: brown;"&gt;&lt;b&gt;//&lt;/b&gt;&lt;/span&gt;;&lt;br /&gt;&lt;span style="color: brown;"&gt;30 &lt;/span&gt;    given (&lt;span style="color: darkcyan;"&gt;$command&lt;/span&gt;) {&lt;br /&gt;&lt;span style="color: brown;"&gt;31 &lt;/span&gt;        when ( looks_like_number(&lt;span style="color: darkcyan;"&gt;$_&lt;/span&gt;) ) { &lt;span style="color: darkcyan;"&gt;$s&lt;/span&gt;&lt;span style="color: darkcyan;"&gt;-&amp;gt;add_data&lt;/span&gt;(&lt;span style="color: darkcyan;"&gt;$command&lt;/span&gt;) }&lt;br /&gt;&lt;span style="color: brown;"&gt;32 &lt;/span&gt;        when (&lt;span style="color: darkcyan;"&gt;%FUNCS&lt;/span&gt;)                  { say &lt;span style="color: magenta;"&gt;"&lt;/span&gt;&lt;span style="color: darkcyan;"&gt;$command&lt;/span&gt;&lt;span style="color: magenta;"&gt; = &lt;/span&gt;&lt;span style="color: magenta;"&gt;"&lt;/span&gt; . &lt;span style="color: darkcyan;"&gt;$s&lt;/span&gt;-&amp;gt;&lt;span style="color: darkcyan;"&gt;$command&lt;/span&gt; }&lt;br /&gt;&lt;span style="color: brown;"&gt;33 &lt;/span&gt;        when (&lt;span style="color: magenta;"&gt;"&lt;/span&gt;&lt;span style="color: magenta;"&gt;man&lt;/span&gt;&lt;span style="color: magenta;"&gt;"&lt;/span&gt;)                   { man&lt;span style="color: magenta;"&gt; "&lt;/span&gt;&lt;span style="color: magenta;"&gt;Statistics::Descriptive&lt;/span&gt;&lt;span style="color: magenta;"&gt;"&lt;/span&gt; }&lt;br /&gt;&lt;span style="color: brown;"&gt;34 &lt;/span&gt;        when ( [ &lt;span style="color: magenta;"&gt;"&lt;/span&gt;&lt;span style="color: magenta;"&gt;exit&lt;/span&gt;&lt;span style="color: magenta;"&gt;"&lt;/span&gt;, &lt;span style="color: magenta;"&gt;"&lt;/span&gt;&lt;span style="color: magenta;"&gt;quit&lt;/span&gt;&lt;span style="color: magenta;"&gt;"&lt;/span&gt; ] )    {&lt;span style="color: brown;"&gt;&lt;b&gt; last&lt;/b&gt;&lt;/span&gt; }&lt;br /&gt;&lt;span style="color: brown;"&gt;35 &lt;/span&gt;        when (&lt;span style="color: magenta;"&gt;"&lt;/span&gt;&lt;span style="color: magenta;"&gt;help&lt;/span&gt;&lt;span style="color: magenta;"&gt;"&lt;/span&gt;)                  { help }&lt;br /&gt;&lt;span style="color: brown;"&gt;36 &lt;/span&gt;        default                        { say SYNTAX_ERROR }&lt;br /&gt;&lt;span style="color: brown;"&gt;37 &lt;/span&gt;    }&lt;br /&gt;&lt;span style="color: brown;"&gt;38 &lt;/span&gt;}&lt;br /&gt;&lt;/pre&gt;En el &lt;a href="http://perliscopio.blogspot.com/2009/09/calculadora-estadistica-consola.html"&gt;próximo articulo&lt;/a&gt; seguiremos agregando características a la calculadora para hacerla más amigable.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5238463735728501931-5705454436703813678?l=perliscopio.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://perliscopio.blogspot.com/feeds/5705454436703813678/comments/default' title='Enviar comentarios'/><link rel='replies' type='text/html' href='http://perliscopio.blogspot.com/2009/09/calculadora-estadistica-usando-el.html#comment-form' title='0 comentarios'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5238463735728501931/posts/default/5705454436703813678'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5238463735728501931/posts/default/5705454436703813678'/><link rel='alternate' type='text/html' href='http://perliscopio.blogspot.com/2009/09/calculadora-estadistica-usando-el.html' title='Calculadora Estadística: Usando el sistema'/><author><name>Jose Rey</name><uri>http://www.blogger.com/profile/15071755167581242815</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5238463735728501931.post-5776083786445760284</id><published>2009-09-18T09:31:00.003-04:30</published><updated>2009-09-23T11:14:35.483-04:30</updated><category scheme='http://www.blogger.com/atom/ns#' term='Tutorial'/><category scheme='http://www.blogger.com/atom/ns#' term='Perl'/><category scheme='http://www.blogger.com/atom/ns#' term='Estilo'/><category scheme='http://www.blogger.com/atom/ns#' term='Programación'/><title type='text'>Perl inteligente</title><content type='html'>[&lt;a href="http://perliscope.blogspot.com/2009/09/smart-perl.html"&gt;English translation&lt;/a&gt;]&lt;br /&gt;En el &lt;a href="http://perliscopio.blogspot.com/2009/09/usando-perl-moderno.html"&gt;artículo anterior&lt;/a&gt; vimos un ejemplo de &lt;a href="http://perliscopio.blogspot.com/2009/09/usando-perl-moderno.html"&gt;Perl moderno&lt;/a&gt;, hoy vamos a profundizar un poquito más en la comparación inteligente de Perl 5.10 y como al combinarla con las características dinámicas del lenguaje obtenemos un programa ridículamente pequeño, pero más fácil de comprender y mantener.&lt;br /&gt;Alguna vez leí (creo que de &lt;a href="http://www.paulgraham.com/articles.html"&gt;Paul Graham&lt;/a&gt;) que cuando alguna sección de código parece duplicada generalmente hace falta un nivel de abstracción, claro que él programa en Lisp, y tiene &lt;a href="http://www.apl.jhu.edu/%7Ehall/Lisp-Notes/Macros.html"&gt;defmacro&lt;/a&gt;. Sin embargo Perl también tiene lo suyo, y en este caso nuestra primera solución podría basarse en un hash que incluya las funciones permitidas en nuestra calculadora:&lt;br /&gt;&lt;pre&gt;&lt;span style="color: brown;"&gt; 1 &lt;/span&gt;&lt;span style="color: #a020f0;"&gt;#!/usr/bin/perl&lt;/span&gt;&lt;br /&gt;&lt;span style="color: brown;"&gt; 2 &lt;/span&gt;&lt;br /&gt;&lt;span style="color: brown;"&gt; 3 &lt;/span&gt;&lt;span style="color: #a020f0;"&gt;use &lt;/span&gt;Modern::Perl;&lt;br /&gt;&lt;span style="color: brown;"&gt; 4 &lt;/span&gt;&lt;span style="color: #a020f0;"&gt;use &lt;/span&gt;Scalar::Util &lt;span style="color: magenta;"&gt;qw(&lt;/span&gt;&lt;span style="color: magenta;"&gt; looks_like_number &lt;/span&gt;&lt;span style="color: magenta;"&gt;)&lt;/span&gt;;&lt;br /&gt;&lt;span style="color: brown;"&gt; 5 &lt;/span&gt;&lt;span style="color: #a020f0;"&gt;use &lt;/span&gt;Statistics::Descriptive;&lt;br /&gt;&lt;span style="color: brown;"&gt; 6 &lt;/span&gt;&lt;br /&gt;&lt;span style="color: brown;"&gt; 7 &lt;/span&gt;&lt;span style="color: #a020f0;"&gt;use constant&lt;/span&gt; &lt;span style="color: magenta;"&gt;SYNTAX_ERROR &lt;/span&gt;=&amp;gt; &lt;span style="color: magenta;"&gt;"&lt;/span&gt;&lt;span style="color: magenta;"&gt;Error: tipee 'help' para ayuda&lt;/span&gt;&lt;span style="color: magenta;"&gt;"&lt;/span&gt;;&lt;br /&gt;&lt;span style="color: brown;"&gt; 8 &lt;/span&gt;&lt;br /&gt;&lt;span style="color: brown;"&gt; 9 &lt;/span&gt;&lt;span style="color: brown;"&gt;&lt;b&gt;my&lt;/b&gt;&lt;/span&gt; &lt;span style="color: darkcyan;"&gt;%FUNCS&lt;/span&gt; = (&lt;br /&gt;&lt;span style="color: brown;"&gt;10 &lt;/span&gt;    &lt;span style="color: magenta;"&gt;sum                &lt;/span&gt;=&amp;gt; &lt;span style="color: magenta;"&gt;0&lt;/span&gt;,&lt;br /&gt;&lt;span style="color: brown;"&gt;11 &lt;/span&gt;    &lt;span style="color: magenta;"&gt;mean               &lt;/span&gt;=&amp;gt; &lt;span style="color: magenta;"&gt;0&lt;/span&gt;,&lt;br /&gt;&lt;span style="color: brown;"&gt;12 &lt;/span&gt;    &lt;span style="color: magenta;"&gt;count              &lt;/span&gt;=&amp;gt; &lt;span style="color: magenta;"&gt;0&lt;/span&gt;,&lt;br /&gt;&lt;span style="color: brown;"&gt;13 &lt;/span&gt;    &lt;span style="color: magenta;"&gt;variance           &lt;/span&gt;=&amp;gt; &lt;span style="color: magenta;"&gt;0&lt;/span&gt;,&lt;br /&gt;&lt;span style="color: brown;"&gt;14 &lt;/span&gt;    &lt;span style="color: magenta;"&gt;standard_deviation &lt;/span&gt;=&amp;gt; &lt;span style="color: magenta;"&gt;0&lt;/span&gt;,&lt;br /&gt;&lt;span style="color: brown;"&gt;15 &lt;/span&gt;    &lt;span style="color: magenta;"&gt;min                &lt;/span&gt;=&amp;gt; &lt;span style="color: magenta;"&gt;0&lt;/span&gt;,&lt;br /&gt;&lt;span style="color: brown;"&gt;16 &lt;/span&gt;    &lt;span style="color: magenta;"&gt;mindex             &lt;/span&gt;=&amp;gt; &lt;span style="color: magenta;"&gt;0&lt;/span&gt;,&lt;br /&gt;&lt;span style="color: brown;"&gt;17 &lt;/span&gt;    &lt;span style="color: magenta;"&gt;max                &lt;/span&gt;=&amp;gt; &lt;span style="color: magenta;"&gt;0&lt;/span&gt;,&lt;br /&gt;&lt;span style="color: brown;"&gt;18 &lt;/span&gt;    &lt;span style="color: magenta;"&gt;maxdex             &lt;/span&gt;=&amp;gt; &lt;span style="color: magenta;"&gt;0&lt;/span&gt;,&lt;br /&gt;&lt;span style="color: brown;"&gt;19 &lt;/span&gt;    &lt;span style="color: magenta;"&gt;sample_range       &lt;/span&gt;=&amp;gt; &lt;span style="color: magenta;"&gt;0&lt;/span&gt;,&lt;br /&gt;&lt;span style="color: brown;"&gt;20 &lt;/span&gt;    &lt;span style="color: magenta;"&gt;median             &lt;/span&gt;=&amp;gt; &lt;span style="color: magenta;"&gt;0&lt;/span&gt;,&lt;br /&gt;&lt;span style="color: brown;"&gt;21 &lt;/span&gt;    &lt;span style="color: magenta;"&gt;harmonic_mean      &lt;/span&gt;=&amp;gt; &lt;span style="color: magenta;"&gt;0&lt;/span&gt;,&lt;br /&gt;&lt;span style="color: brown;"&gt;22 &lt;/span&gt;    &lt;span style="color: magenta;"&gt;geometric_mean     &lt;/span&gt;=&amp;gt; &lt;span style="color: magenta;"&gt;0&lt;/span&gt;,&lt;br /&gt;&lt;span style="color: brown;"&gt;23 &lt;/span&gt;    &lt;span style="color: magenta;"&gt;mode               &lt;/span&gt;=&amp;gt; &lt;span style="color: magenta;"&gt;0&lt;/span&gt;,&lt;br /&gt;&lt;span style="color: brown;"&gt;24 &lt;/span&gt;    &lt;span style="color: magenta;"&gt;trimmed_mean       &lt;/span&gt;=&amp;gt; &lt;span style="color: magenta;"&gt;0&lt;/span&gt;,&lt;br /&gt;&lt;span style="color: brown;"&gt;25 &lt;/span&gt;);&lt;br /&gt;&lt;span style="color: brown;"&gt;26 &lt;/span&gt;&lt;br /&gt;&lt;span style="color: brown;"&gt;27 &lt;/span&gt;&lt;span style="color: brown;"&gt;&lt;b&gt;my&lt;/b&gt;&lt;/span&gt; &lt;span style="color: darkcyan;"&gt;$s&lt;/span&gt; = Statistics::Descriptive::Full-&amp;gt;&lt;span style="color: brown;"&gt;&lt;b&gt;new&lt;/b&gt;&lt;/span&gt;();&lt;br /&gt;&lt;span style="color: brown;"&gt;28 &lt;/span&gt;&lt;span style="color: brown;"&gt;&lt;b&gt;while&lt;/b&gt;&lt;/span&gt; (&lt;span style="color: magenta;"&gt;1&lt;/span&gt;) {&lt;br /&gt;&lt;span style="color: brown;"&gt;29 &lt;/span&gt;    &lt;span style="color: brown;"&gt;&lt;b&gt;print&lt;/b&gt;&lt;/span&gt; &lt;span style="color: magenta;"&gt;"&lt;/span&gt;&lt;span style="color: magenta;"&gt;Listo&amp;gt; &lt;/span&gt;&lt;span style="color: magenta;"&gt;"&lt;/span&gt;;&lt;br /&gt;&lt;span style="color: brown;"&gt;30 &lt;/span&gt;    &lt;span style="color: brown;"&gt;&lt;b&gt;my&lt;/b&gt;&lt;/span&gt; &lt;span style="color: darkcyan;"&gt;$command&lt;/span&gt; = &lt;span style="color: brown;"&gt;&lt;b&gt;readline&lt;/b&gt;&lt;/span&gt;(&lt;span style="color: darkcyan;"&gt;STDIN&lt;/span&gt;) &lt;span style="color: brown;"&gt;&lt;b&gt;//&lt;/b&gt;&lt;/span&gt; &lt;span style="color: brown;"&gt;&lt;b&gt;last&lt;/b&gt;&lt;/span&gt;;&lt;br /&gt;&lt;span style="color: brown;"&gt;31 &lt;/span&gt;    &lt;span style="color: darkcyan;"&gt;$command&lt;/span&gt; =~ &lt;span style="color: brown;"&gt;&lt;b&gt;s/&lt;/b&gt;&lt;/span&gt;&lt;span style="color: magenta;"&gt;^&lt;/span&gt;&lt;span style="color: slateblue;"&gt;\s&lt;/span&gt;&lt;span style="color: slateblue;"&gt;+&lt;/span&gt;&lt;span style="color: brown;"&gt;&lt;b&gt;//&lt;/b&gt;&lt;/span&gt;; &lt;span style="color: darkcyan;"&gt;$command&lt;/span&gt; =~ &lt;span style="color: brown;"&gt;&lt;b&gt;s/&lt;/b&gt;&lt;/span&gt;&lt;span style="color: slateblue;"&gt;\s&lt;/span&gt;&lt;span style="color: slateblue;"&gt;+&lt;/span&gt;&lt;span style="color: magenta;"&gt;$&lt;/span&gt;&lt;span style="color: brown;"&gt;&lt;b&gt;//&lt;/b&gt;&lt;/span&gt;;&lt;br /&gt;&lt;span style="color: brown;"&gt;32 &lt;/span&gt;    given (&lt;span style="color: darkcyan;"&gt;$command&lt;/span&gt;) {&lt;br /&gt;&lt;span style="color: brown;"&gt;33 &lt;/span&gt;        when ( looks_like_number(&lt;span style="color: darkcyan;"&gt;$_&lt;/span&gt;) ) { &lt;span style="color: darkcyan;"&gt;$s&lt;/span&gt;&lt;span style="color: darkcyan;"&gt;-&amp;gt;add_data&lt;/span&gt;(&lt;span style="color: darkcyan;"&gt;$command&lt;/span&gt;) }&lt;br /&gt;&lt;span style="color: brown;"&gt;34 &lt;/span&gt;        when (&lt;span style="color: brown;"&gt;&lt;b&gt;/&lt;/b&gt;&lt;/span&gt;&lt;span style="color: magenta;"&gt;^&lt;/span&gt;&lt;span style="color: slateblue;"&gt;(&lt;/span&gt;&lt;span style="color: magenta;"&gt;exit|quit&lt;/span&gt;&lt;span style="color: slateblue;"&gt;)&lt;/span&gt;&lt;span style="color: magenta;"&gt;$&lt;/span&gt;&lt;span style="color: brown;"&gt;&lt;b&gt;/&lt;/b&gt;&lt;/span&gt;)         {&lt;span style="color: brown;"&gt;&lt;b&gt;last&lt;/b&gt;&lt;/span&gt;}&lt;br /&gt;&lt;span style="color: brown;"&gt;35 &lt;/span&gt;        default {&lt;br /&gt;&lt;span style="color: brown;"&gt;36 &lt;/span&gt;            &lt;span style="color: brown;"&gt;&lt;b&gt;if&lt;/b&gt;&lt;/span&gt;   ( &lt;span style="color: brown;"&gt;&lt;b&gt;exists&lt;/b&gt;&lt;/span&gt; &lt;span style="color: darkcyan;"&gt;$FUNCS{$command}&lt;/span&gt; ) { ... }&lt;br /&gt;&lt;span style="color: brown;"&gt;37 &lt;/span&gt;            &lt;span style="color: brown;"&gt;&lt;b&gt;else&lt;/b&gt;&lt;/span&gt;                             { say &lt;span style="color: darkcyan;"&gt;SYNTAX_ERROR&lt;/span&gt;}&lt;br /&gt;&lt;span style="color: brown;"&gt;38 &lt;/span&gt;        }&lt;br /&gt;&lt;span style="color: brown;"&gt;39 &lt;/span&gt;    }&lt;br /&gt;&lt;span style="color: brown;"&gt;40 &lt;/span&gt;}&lt;br /&gt;&lt;/pre&gt;Esto es un avance importante, porque estamos simplificando el código en la parte complicada del programa, y reemplazándolo por una simple declaración de un hash, donde incluir una nueva función es tan simple como agregar una línea.&lt;br /&gt;Claro que cualquier lector astuto se ha dado cuenta de que hago trampa porque el programa está incompleto; la línea 36 necesita una acción, nuestro problema ahora es como ejecutar el método correcto para la operación, y en Perl como de costumbre hay varias formas de hacerlo, una de ellas (la peor) podría utilizar referencias a las funciones de la clase en el hash, así:&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;span style="color: brown;"&gt;10 &lt;/span&gt;    &lt;span style="color: magenta;"&gt;sum  &lt;/span&gt;=&amp;gt; \&amp;amp;Statistics::Descriptive::sum,&lt;/pre&gt;Para luego hacer algo como:&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;span style="color: brown;"&gt;36 &lt;/span&gt;    &lt;span style="color: brown;"&gt;&lt;b&gt;if&lt;/b&gt;&lt;/span&gt; ( &lt;span style="color: brown;"&gt;&lt;b&gt;exists&lt;/b&gt;&lt;/span&gt; &lt;span style="color: darkcyan;"&gt;$FUNCS{$command}&lt;/span&gt; ) { say &lt;span style="color: magenta;"&gt;"&lt;/span&gt;&lt;span style="color: darkcyan;"&gt;$command&lt;/span&gt;&lt;span style="color: magenta;"&gt; = &lt;/span&gt;&lt;span style="color: magenta;"&gt;"&lt;/span&gt; . &lt;span style="color: darkcyan;"&gt;$FUNCS{$command}(&lt;/span&gt;&lt;span style="color: darkcyan;"&gt;$s)&lt;/span&gt; }&lt;br /&gt;&lt;/pre&gt;Digo que esa es la peor forma porque hay que saber mucho Perl para entender como funciona eso, y Perl tiene la capacidad de despachar métodos simbólicamente haciendo que nuestra intención quede perfectamente clara:&lt;br /&gt;&lt;pre&gt;&lt;span style="color: brown;"&gt;36 &lt;/span&gt;    &lt;span style="color: brown;"&gt;&lt;b&gt;if&lt;/b&gt;&lt;/span&gt; ( &lt;span style="color: brown;"&gt;&lt;b&gt;exists&lt;/b&gt;&lt;/span&gt; &lt;span style="color: darkcyan;"&gt;$FUNCS{$command}&lt;/span&gt; ) { say &lt;span style="color: magenta;"&gt;"&lt;/span&gt;&lt;span style="color: darkcyan;"&gt;$command&lt;/span&gt;&lt;span style="color: magenta;"&gt; = &lt;/span&gt;&lt;span style="color: magenta;"&gt;"&lt;/span&gt; . &lt;span style="color: darkcyan;"&gt;$s-&amp;gt;$command&lt;/span&gt; }&lt;/pre&gt;El costo de esta operación es mayor que el de la alternativa anterior, sin embargo es un precio que se paga con gusto, porque el programa es mucho más fácil de entender, y últimamente la gente es mucho más cara que las máquinas.&lt;br /&gt;Finalmente si la flojera es uno de tus principios fundamentales, puedes reescribir la asignación del hash así:&lt;br /&gt;&lt;pre&gt;&lt;span style="color: brown;"&gt; 9 &lt;/span&gt;&lt;span style="color: brown;"&gt;&lt;b&gt;my&lt;/b&gt;&lt;/span&gt; &lt;span style="color: darkcyan;"&gt;%FUNCS&lt;/span&gt; = &lt;span style="color: brown;"&gt;&lt;b&gt;map&lt;/b&gt;&lt;/span&gt; { &lt;span style="color: darkcyan;"&gt;$_&lt;/span&gt; =&amp;gt; &lt;span style="color: magenta;"&gt;0&lt;/span&gt; } &lt;span style="color: magenta;"&gt;qw(&lt;/span&gt;&lt;span style="color: magenta;"&gt; sum mean count variance standard_deviation&lt;/span&gt;&lt;br /&gt;&lt;span style="color: brown;"&gt;10 &lt;/span&gt;&lt;span style="color: magenta;"&gt;    min mindex max maxdex sample_range median harmonic_mean geometric_mean&lt;/span&gt;&lt;br /&gt;&lt;span style="color: brown;"&gt;11 &lt;/span&gt;&lt;span style="color: magenta;"&gt;    mode trimmed_mean &lt;/span&gt;&lt;span style="color: magenta;"&gt;)&lt;/span&gt;;&lt;br /&gt;&lt;/pre&gt;Lo que particularmente aprecio, porque ahorro puntuación (lo que parece abrumar a mucha gente) y tengo menos probabilidad de cometer un error de sintaxis.&lt;br /&gt;Básicamente estoy construyendo una lista de palabras (los nombres de los métodos) con "qw", a partir de esta lista construyo otra (usando &lt;a href="http://perldoc.perl.org/functions/map.html"&gt;map&lt;/a&gt;) que contiene cada elemento de la lista original ($_) acompañado del número&amp;nbsp; 0, perl convierte automáticamente esta lista en un hash donde cada nombre tiene asociado 0 como valor.&lt;br /&gt;Si la explicación anterior te parece complicada o incomprensible, puedes ver la documentación de  &lt;a href="http://perldoc.perl.org/functions/map.html"&gt;map&lt;/a&gt; en Perl, lo que te vendrá de maravilla porque además podrás aprender algo de &lt;a href="http://pfactorial.wordpress.com/2007/09/04/mi-pequena-obsesion-con-la-programacion-funcional-parte-01/"&gt;programación funcional&lt;/a&gt; que de seguro te &lt;a href="http://pfactorial.wordpress.com/2007/09/05/mi-pequena-obsesion-con-la-programacion-funcional-parte-02/"&gt;será muy provechoso&lt;/a&gt;.&lt;br /&gt;Ahora me voy a deshacer del "if", prefiero los condicionales de múltiples vias, son más planos y se ve mejor el flujo, por eso opino que el given/when es lo mejor que le ha pasado a Perl en mucho tiempo, además me voy a deshacer de la expresión regular en la línea 34 por algo que tenga más sentido para un extraño a Perl:&lt;br /&gt;&lt;pre&gt;&lt;span style="color: brown;"&gt; 1 &lt;/span&gt;&lt;span style="color: #a020f0;"&gt;#!/usr/bin/perl&lt;/span&gt;&lt;br /&gt;&lt;span style="color: brown;"&gt; 2 &lt;/span&gt;&lt;br /&gt;&lt;span style="color: brown;"&gt; 3 &lt;/span&gt;&lt;span style="color: #a020f0;"&gt;use &lt;/span&gt;Modern::Perl;&lt;br /&gt;&lt;span style="color: brown;"&gt; 4 &lt;/span&gt;&lt;span style="color: #a020f0;"&gt;use &lt;/span&gt;Scalar::Util &lt;span style="color: magenta;"&gt;qw(&lt;/span&gt;&lt;span style="color: magenta;"&gt; looks_like_number &lt;/span&gt;&lt;span style="color: magenta;"&gt;)&lt;/span&gt;;&lt;br /&gt;&lt;span style="color: brown;"&gt; 5 &lt;/span&gt;&lt;span style="color: #a020f0;"&gt;use &lt;/span&gt;Statistics::Descriptive;&lt;br /&gt;&lt;span style="color: brown;"&gt; 6 &lt;/span&gt;&lt;br /&gt;&lt;span style="color: brown;"&gt; 7 &lt;/span&gt;&lt;span style="color: #a020f0;"&gt;use constant&lt;/span&gt; &lt;span style="color: magenta;"&gt;SYNTAX_ERROR &lt;/span&gt;=&amp;gt; &lt;span style="color: magenta;"&gt;"&lt;/span&gt;&lt;span style="color: magenta;"&gt;Error: tipee 'help' para ayuda&lt;/span&gt;&lt;span style="color: magenta;"&gt;"&lt;/span&gt;;&lt;br /&gt;&lt;span style="color: brown;"&gt; 8 &lt;/span&gt;&lt;br /&gt;&lt;span style="color: brown;"&gt; 9 &lt;/span&gt;&lt;span style="color: brown;"&gt;&lt;b&gt;my&lt;/b&gt;&lt;/span&gt; &lt;span style="color: darkcyan;"&gt;%FUNCS&lt;/span&gt; = &lt;span style="color: brown;"&gt;&lt;b&gt;map&lt;/b&gt;&lt;/span&gt; { &lt;span style="color: darkcyan;"&gt;$_&lt;/span&gt; =&amp;gt; &lt;span style="color: magenta;"&gt;1&lt;/span&gt; } &lt;span style="color: magenta;"&gt;qw(&lt;/span&gt;&lt;span style="color: magenta;"&gt; sum mean count variance standard_deviation&lt;/span&gt;&lt;br /&gt;&lt;span style="color: brown;"&gt;10 &lt;/span&gt;&lt;span style="color: magenta;"&gt;    min mindex max maxdex sample_range median harmonic_mean geometric_mean&lt;/span&gt;&lt;br /&gt;&lt;span style="color: brown;"&gt;11 &lt;/span&gt;&lt;span style="color: magenta;"&gt;    mode trimmed_mean &lt;/span&gt;&lt;span style="color: magenta;"&gt;)&lt;/span&gt;;&lt;br /&gt;&lt;span style="color: brown;"&gt;12 &lt;/span&gt;&lt;br /&gt;&lt;span style="color: brown;"&gt;13 &lt;/span&gt;&lt;span style="color: brown;"&gt;&lt;b&gt;my&lt;/b&gt;&lt;/span&gt; &lt;span style="color: darkcyan;"&gt;$s&lt;/span&gt; = Statistics::Descriptive::Full-&amp;gt;&lt;span style="color: brown;"&gt;&lt;b&gt;new&lt;/b&gt;&lt;/span&gt;();&lt;br /&gt;&lt;span style="color: brown;"&gt;14 &lt;/span&gt;&lt;span style="color: brown;"&gt;&lt;b&gt;while&lt;/b&gt;&lt;/span&gt; (&lt;span style="color: magenta;"&gt;1&lt;/span&gt;) {&lt;br /&gt;&lt;span style="color: brown;"&gt;15 &lt;/span&gt;    &lt;span style="color: brown;"&gt;&lt;b&gt;print&lt;/b&gt;&lt;/span&gt; &lt;span style="color: magenta;"&gt;"&lt;/span&gt;&lt;span style="color: magenta;"&gt;Listo&amp;gt; &lt;/span&gt;&lt;span style="color: magenta;"&gt;"&lt;/span&gt;;&lt;br /&gt;&lt;span style="color: brown;"&gt;16 &lt;/span&gt;    &lt;span style="color: brown;"&gt;&lt;b&gt;my&lt;/b&gt;&lt;/span&gt; &lt;span style="color: darkcyan;"&gt;$command&lt;/span&gt; = &lt;span style="color: brown;"&gt;&lt;b&gt;readline&lt;/b&gt;&lt;/span&gt;(&lt;span style="color: darkcyan;"&gt;STDIN&lt;/span&gt;) &lt;span style="color: brown;"&gt;&lt;b&gt;//&lt;/b&gt;&lt;/span&gt; &lt;span style="color: brown;"&gt;&lt;b&gt;last&lt;/b&gt;&lt;/span&gt;;&lt;br /&gt;&lt;span style="color: brown;"&gt;17 &lt;/span&gt;    &lt;span style="color: darkcyan;"&gt;$command&lt;/span&gt; =~ &lt;span style="color: brown;"&gt;&lt;b&gt;s/&lt;/b&gt;&lt;/span&gt;&lt;span style="color: magenta;"&gt;^&lt;/span&gt;&lt;span style="color: slateblue;"&gt;\s&lt;/span&gt;&lt;span style="color: slateblue;"&gt;+&lt;/span&gt;&lt;span style="color: brown;"&gt;&lt;b&gt;//&lt;/b&gt;&lt;/span&gt;; &lt;span style="color: darkcyan;"&gt;$command&lt;/span&gt; =~ &lt;span style="color: brown;"&gt;&lt;b&gt;s/&lt;/b&gt;&lt;/span&gt;&lt;span style="color: slateblue;"&gt;\s&lt;/span&gt;&lt;span style="color: slateblue;"&gt;+&lt;/span&gt;&lt;span style="color: magenta;"&gt;$&lt;/span&gt;&lt;span style="color: brown;"&gt;&lt;b&gt;//&lt;/b&gt;&lt;/span&gt;;&lt;br /&gt;&lt;span style="color: brown;"&gt;18 &lt;/span&gt;    given (&lt;span style="color: darkcyan;"&gt;$command&lt;/span&gt;) {&lt;br /&gt;&lt;span style="color: brown;"&gt;19 &lt;/span&gt;        when ( looks_like_number(&lt;span style="color: darkcyan;"&gt;$_&lt;/span&gt;) ) { &lt;span style="color: darkcyan;"&gt;$s&lt;/span&gt;&lt;span style="color: darkcyan;"&gt;-&amp;gt;add_data&lt;/span&gt;(&lt;span style="color: darkcyan;"&gt;$command&lt;/span&gt;) }&lt;br /&gt;&lt;span style="color: brown;"&gt;20 &lt;/span&gt;        when ( [&lt;span style="color: magenta;"&gt;"&lt;/span&gt;&lt;span style="color: magenta;"&gt;exit&lt;/span&gt;&lt;span style="color: magenta;"&gt;"&lt;/span&gt;, &lt;span style="color: magenta;"&gt;"&lt;/span&gt;&lt;span style="color: magenta;"&gt;quit&lt;/span&gt;&lt;span style="color: magenta;"&gt;"&lt;/span&gt;] )      {&lt;span style="color: brown;"&gt;&lt;b&gt;last&lt;/b&gt;&lt;/span&gt;}&lt;br /&gt;&lt;span style="color: brown;"&gt;21 &lt;/span&gt;        when (&lt;span style="color: darkcyan;"&gt;%FUNCS&lt;/span&gt;)                  { say &lt;span style="color: magenta;"&gt;"&lt;/span&gt;&lt;span style="color: darkcyan;"&gt;$command&lt;/span&gt;&lt;span style="color: magenta;"&gt; = &lt;/span&gt;&lt;span style="color: magenta;"&gt;"&lt;/span&gt; . &lt;span style="color: darkcyan;"&gt;$s&lt;/span&gt;-&amp;gt;&lt;span style="color: darkcyan;"&gt;$command&lt;/span&gt; }&lt;br /&gt;&lt;span style="color: brown;"&gt;22 &lt;/span&gt;        default                        { say SYNTAX_ERROR }&lt;br /&gt;&lt;span style="color: brown;"&gt;23 &lt;/span&gt;    }&lt;br /&gt;&lt;span style="color: brown;"&gt;24 &lt;/span&gt;}&lt;br /&gt;&lt;/pre&gt;Ahora se ve mucho mejor (hasta parece &lt;a href="http://radarlibre.blogspot.com/search?q=Erlang"&gt;Erlang&lt;/a&gt;).&lt;br /&gt;Me estoy valiendo de algunas&amp;nbsp; funciones del smart matching que explicaré a continuación.&lt;br /&gt;En la línea 20 se compara un valor contra un arreglo:&lt;br /&gt;&lt;pre&gt;&lt;span style="color: darkcyan;"&gt;$command ~~ &lt;/span&gt;[&lt;span style="color: magenta;"&gt;"&lt;/span&gt;&lt;span style="color: magenta;"&gt;exit&lt;/span&gt;&lt;span style="color: magenta;"&gt;"&lt;/span&gt;, &lt;span style="color: magenta;"&gt;"&lt;/span&gt;&lt;span style="color: magenta;"&gt;quit&lt;/span&gt;&lt;span style="color: magenta;"&gt;"&lt;/span&gt;]&lt;/pre&gt;Cuando se compara un escalar (a la izquierda) contra un arreglo (a la derecha) el efecto es equivalente a lo siguiente:&lt;br /&gt;&lt;pre&gt;&lt;span style="color: brown;"&gt;&lt;b&gt;sub&lt;/b&gt;&lt;/span&gt;&lt;span style="color: darkcyan;"&gt; &lt;/span&gt;&lt;span style="color: darkcyan;"&gt;match_scalar_arrayref &lt;/span&gt;{&lt;br /&gt;    &lt;span style="color: brown;"&gt;&lt;b&gt;my&lt;/b&gt;&lt;/span&gt; (&lt;span style="color: darkcyan;"&gt;$scalar&lt;/span&gt;, &lt;span style="color: darkcyan;"&gt;$arrayref&lt;/span&gt;) = &lt;span style="color: darkcyan;"&gt;@_&lt;/span&gt;;&lt;br /&gt;    &lt;span style="color: brown;"&gt;&lt;b&gt;for&lt;/b&gt;&lt;/span&gt; &lt;span style="color: brown;"&gt;&lt;b&gt;my&lt;/b&gt;&lt;/span&gt; &lt;span style="color: darkcyan;"&gt;$item&lt;/span&gt; ( &lt;span style="color: darkcyan;"&gt;@$arrayref&lt;/span&gt; ) {&lt;br /&gt;        &lt;span style="color: brown;"&gt;&lt;b&gt;return&lt;/b&gt;&lt;/span&gt; &lt;span style="color: magenta;"&gt;1&lt;/span&gt; &lt;span style="color: brown;"&gt;&lt;b&gt;if&lt;/b&gt;&lt;/span&gt; &lt;span style="color: darkcyan;"&gt;$scalar&lt;/span&gt; &lt;span style="color: brown;"&gt;&lt;b&gt;eq&lt;/b&gt;&lt;/span&gt; &lt;span style="color: darkcyan;"&gt;$item&lt;/span&gt;;&lt;br /&gt;    }&lt;br /&gt;    &lt;span style="color: brown;"&gt;&lt;b&gt;return&lt;/b&gt;&lt;/span&gt; &lt;span style="color: brown;"&gt;&lt;b&gt;undef&lt;/b&gt;&lt;/span&gt;;&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;Ya no recuerdo cuantas veces he escrito código como ese, o como este:&lt;br /&gt;&lt;pre&gt;&lt;span style="color: brown;"&gt;&lt;b&gt;if&lt;/b&gt;&lt;/span&gt; ( &lt;span style="color: brown;"&gt;&lt;b&gt;grep&lt;/b&gt;&lt;/span&gt; { &lt;span style="color: darkcyan;"&gt;$scalar&lt;/span&gt; &lt;span style="color: brown;"&gt;&lt;b&gt;eq&lt;/b&gt;&lt;/span&gt; &lt;span style="color: darkcyan;"&gt;$_&lt;/span&gt; } &lt;span style="color: darkcyan;"&gt;@$arrayref&lt;/span&gt; ) ...&lt;br /&gt;&lt;/pre&gt;Y que&amp;nbsp; ahora podré escribir con mas claridad y menos esfuerzo:&lt;br /&gt;&lt;pre&gt;&lt;span style="color: brown;"&gt;&lt;b&gt;if&lt;/b&gt;&lt;/span&gt; ( &lt;span style="color: darkcyan;"&gt;$scalar&lt;/span&gt; ~~ &lt;span style="color: darkcyan;"&gt;$arrayref&lt;/span&gt; ) ...&lt;br /&gt;&lt;/pre&gt;Probablemente ya adivinaste que en la línea 21, el smart match entre un escalar y un hash es equivalente a:&lt;br /&gt;&lt;pre&gt;&lt;span style="color: brown;"&gt;&lt;b&gt;&lt;/b&gt;&lt;/span&gt;&lt;span style="color: brown;"&gt;&lt;b&gt;if&lt;/b&gt;&lt;/span&gt; ( &lt;span style="color: brown;"&gt;&lt;b&gt;exists&lt;/b&gt;&lt;/span&gt; &lt;span style="color: darkcyan;"&gt;$hash{$scalar}&lt;/span&gt; ) ...&lt;br /&gt;&lt;/pre&gt;&lt;h2&gt;Un poco de tentación&lt;/h2&gt;Una sugerencia que recibí de un lector daba una solución todavía más corta y fácil de mantener, la idea era cambiar la línea:&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;span style="color: brown;"&gt;21 &lt;/span&gt;   when (&lt;span style="color: darkcyan;"&gt;%FUNCS&lt;/span&gt;) { say &lt;span style="color: magenta;"&gt;"&lt;/span&gt;&lt;span style="color: darkcyan;"&gt;$command&lt;/span&gt;&lt;span style="color: magenta;"&gt; = &lt;/span&gt;&lt;span style="color: magenta;"&gt;"&lt;/span&gt; . &lt;span style="color: darkcyan;"&gt;$s&lt;/span&gt;-&amp;gt;&lt;span style="color: darkcyan;"&gt;$command&lt;/span&gt; }&lt;/pre&gt;por:&lt;br /&gt;&lt;pre&gt;&lt;span style="color: brown;"&gt;21 &lt;/span&gt;   when (&lt;span style="color: darkcyan;"&gt;$s-&amp;gt;can($command)&lt;/span&gt;) { say &lt;span style="color: magenta;"&gt;"&lt;/span&gt;&lt;span style="color: darkcyan;"&gt;$command&lt;/span&gt;&lt;span style="color: magenta;"&gt; = &lt;/span&gt;&lt;span style="color: magenta;"&gt;"&lt;/span&gt; . &lt;span style="color: darkcyan;"&gt;$s&lt;/span&gt;-&amp;gt;&lt;span style="color: darkcyan;"&gt;$command&lt;/span&gt; }&lt;/pre&gt;El método can es provisto por la clase UNIVERSAL, de la cual derivan todos los objetos en Perl, y el propósito de este método es averiguar si un objeto o clase tiene un método determinado.&lt;br /&gt;Al utilizar esta mejora ni siquiera necesito el hash %FUNCS, y además nuestro interpretador se actualizará automáticamente con nuevos comandos a medida que evolucione Statistics::Descriptive, lo cual suena muy bien desde el punto de vista de mantenibilidad, sin embargo, tiene un problema fatal para mí: no es seguro.&lt;br /&gt;El problema es que pierdo el control sobre lo que Perl ejecuta automáticamente, y aunque probablemente este módulo no pueda hacer mucho daño, esta misma técnica utilizando algún otro módulo, podría ser peligrosa. Así que prefiero la seguridad y me quedo con el hash como mecanismo de despacho (y autorización de uso).&lt;br /&gt;La moraleja es que se debe terner cuidado al utilizar mecanismos de control de ejecución dinámicos, sobre todo cuando se utilizan datos de fuentes externas no confiables en estos mecanismos de control de ejecución.&lt;br /&gt;&lt;h2&gt;Completando el programa&lt;br /&gt;&lt;/h2&gt;&lt;br /&gt;La línea 22 da un error cuando no se conoce un comando, el mensaje dice que use "help" para obtener ayuda, pero el comando "help" todavía no está implementado, una manera rápida de implementarlo es:&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;span style="color: brown;"&gt;23 &lt;/span&gt;        when (&lt;span style="color: magenta;"&gt;"&lt;/span&gt;&lt;span style="color: magenta;"&gt;help&lt;/span&gt;&lt;span style="color: magenta;"&gt;"&lt;/span&gt;) {&lt;br /&gt;&lt;span style="color: brown;"&gt;24 &lt;/span&gt;            say &lt;span style="color: magenta;"&gt;"&lt;/span&gt;&lt;span style="color: magenta;"&gt;Los comandos válidos son: &lt;/span&gt;&lt;span style="color: magenta;"&gt;"&lt;/span&gt;&lt;br /&gt;&lt;span style="color: brown;"&gt;25 &lt;/span&gt;                . &lt;span style="color: brown;"&gt;&lt;b&gt;join&lt;/b&gt;&lt;/span&gt;( &lt;span style="color: magenta;"&gt;"&lt;/span&gt;&lt;span style="color: magenta;"&gt;, &lt;/span&gt;&lt;span style="color: magenta;"&gt;"&lt;/span&gt;, &lt;span style="color: magenta;"&gt;qw(&lt;/span&gt;&lt;span style="color: magenta;"&gt;exit quit help&lt;/span&gt;&lt;span style="color: magenta;"&gt;)&lt;/span&gt;, &lt;span style="color: brown;"&gt;&lt;b&gt;keys&lt;/b&gt;&lt;/span&gt; &lt;span style="color: darkcyan;"&gt;%FUNCS&lt;/span&gt; )&lt;br /&gt;&lt;span style="color: brown;"&gt;26 &lt;/span&gt;        }&lt;/pre&gt;Guau, eso fue fácil, lo mejor es que además de fácil es consistente, porque se utiliza la misma estructura de datos para informar los comandos, para seleccionarlos y para autorizarlos.&lt;br /&gt;Una de las funciones que se me olvidó incluir en la calculadora en el artículo anterior fue "clear", agregar esta función ahora es tan sencillo como poner una nueva palabra en la definición de %FUNCS:&lt;br /&gt;&lt;pre&gt;&lt;span style="color: brown;"&gt; 9 &lt;/span&gt;&lt;span style="color: brown;"&gt;&lt;b&gt;my&lt;/b&gt;&lt;/span&gt; &lt;span style="color: darkcyan;"&gt;%FUNCS&lt;/span&gt; = &lt;span style="color: brown;"&gt;&lt;b&gt;map&lt;/b&gt;&lt;/span&gt; { &lt;span style="color: darkcyan;"&gt;$_&lt;/span&gt; =&amp;gt; &lt;span style="color: magenta;"&gt;1&lt;/span&gt; } &lt;span style="color: magenta;"&gt;qw(&lt;/span&gt;&lt;span style="color: magenta;"&gt; sum mean count variance standard_deviation&lt;/span&gt;&lt;br /&gt;&lt;span style="color: brown;"&gt;10 &lt;/span&gt;&lt;span style="color: magenta;"&gt;    min mindex max maxdex sample_range median harmonic_mean geometric_mean&lt;/span&gt;&lt;br /&gt;&lt;span style="color: brown;"&gt;11 &lt;/span&gt;&lt;span style="color: magenta;"&gt;    mode trimmed_mean clear &lt;/span&gt;&lt;span style="color: magenta;"&gt;)&lt;/span&gt;;&amp;nbsp;&lt;/pre&gt;Fue fácil, ¿o no?. Lo mejor es que el nuevo comando aparece automáticamente en la ayuda porque el programa es consistente.&lt;br /&gt;Recapitulemos los logros del día, tenemos un programa:&lt;br /&gt;&lt;ul&gt;&lt;li&gt;Muy compacto&lt;br /&gt;&lt;/li&gt;&lt;li&gt;Fácil de comprender&lt;br /&gt;&lt;/li&gt;&lt;li&gt;Fácil de mantener&lt;/li&gt;&lt;li&gt;Consistente&lt;/li&gt;&lt;li&gt;Seguro&lt;br /&gt;&lt;/li&gt;&lt;/ul&gt;Perl tan válido como cualquier otro lenguaje, pero además, muy pocos lenguajes brindan mecanismos similares a los aquí expuestos para lograr un programa con estas características.&lt;br /&gt;En el &lt;a href="http://perliscopio.blogspot.com/2009/09/calculadora-estadistica-usando-el.html"&gt;próximo artículo&lt;/a&gt; veremos como agregarle el manual de funciones estadísticas a nuestra calculadora con mucha facilidad. &lt;br /&gt;A continuación los dejo con la versión final del programa:&lt;br /&gt;&lt;pre&gt;&lt;span style="color: brown;"&gt; 1 &lt;/span&gt;&lt;span style="color: #a020f0;"&gt;#!/usr/bin/perl&lt;/span&gt;&lt;br /&gt;&lt;span style="color: brown;"&gt; 2 &lt;/span&gt;&lt;br /&gt;&lt;span style="color: brown;"&gt; 3 &lt;/span&gt;&lt;span style="color: #a020f0;"&gt;use &lt;/span&gt;Modern::Perl;&lt;br /&gt;&lt;span style="color: brown;"&gt; 4 &lt;/span&gt;&lt;span style="color: #a020f0;"&gt;use &lt;/span&gt;Scalar::Util &lt;span style="color: magenta;"&gt;qw(&lt;/span&gt;&lt;span style="color: magenta;"&gt; looks_like_number &lt;/span&gt;&lt;span style="color: magenta;"&gt;)&lt;/span&gt;;&lt;br /&gt;&lt;span style="color: brown;"&gt; 5 &lt;/span&gt;&lt;span style="color: #a020f0;"&gt;use &lt;/span&gt;Statistics::Descriptive;&lt;br /&gt;&lt;span style="color: brown;"&gt; 6 &lt;/span&gt;&lt;br /&gt;&lt;span style="color: brown;"&gt; 7 &lt;/span&gt;&lt;span style="color: #a020f0;"&gt;use constant&lt;/span&gt; &lt;span style="color: magenta;"&gt;SYNTAX_ERROR &lt;/span&gt;=&amp;gt; &lt;span style="color: magenta;"&gt;"&lt;/span&gt;&lt;span style="color: magenta;"&gt;Error: tipee 'help' para ayuda&lt;/span&gt;&lt;span style="color: magenta;"&gt;"&lt;/span&gt;;&lt;br /&gt;&lt;span style="color: brown;"&gt; 8 &lt;/span&gt;&lt;br /&gt;&lt;span style="color: brown;"&gt; 9 &lt;/span&gt;&lt;span style="color: brown;"&gt;&lt;b&gt;my&lt;/b&gt;&lt;/span&gt; &lt;span style="color: darkcyan;"&gt;%FUNCS&lt;/span&gt; = &lt;span style="color: brown;"&gt;&lt;b&gt;map&lt;/b&gt;&lt;/span&gt; { &lt;span style="color: darkcyan;"&gt;$_&lt;/span&gt; =&amp;gt; &lt;span style="color: magenta;"&gt;1&lt;/span&gt; } &lt;span style="color: magenta;"&gt;qw(&lt;/span&gt;&lt;span style="color: magenta;"&gt; sum mean count variance standard_deviation&lt;/span&gt;&lt;br /&gt;&lt;span style="color: brown;"&gt;10 &lt;/span&gt;&lt;span style="color: magenta;"&gt;    min mindex max maxdex sample_range median harmonic_mean geometric_mean&lt;/span&gt;&lt;br /&gt;&lt;span style="color: brown;"&gt;11 &lt;/span&gt;&lt;span style="color: magenta;"&gt;    mode trimmed_mean clear &lt;/span&gt;&lt;span style="color: magenta;"&gt;)&lt;/span&gt;;&lt;br /&gt;&lt;span style="color: brown;"&gt;12 &lt;/span&gt;&lt;br /&gt;&lt;span style="color: brown;"&gt;13 &lt;/span&gt;&lt;span style="color: brown;"&gt;&lt;b&gt;my&lt;/b&gt;&lt;/span&gt; &lt;span style="color: darkcyan;"&gt;$s&lt;/span&gt; = Statistics::Descriptive::Full-&amp;gt;&lt;span style="color: brown;"&gt;&lt;b&gt;new&lt;/b&gt;&lt;/span&gt;();&lt;br /&gt;&lt;span style="color: brown;"&gt;14 &lt;/span&gt;&lt;span style="color: brown;"&gt;&lt;b&gt;while&lt;/b&gt;&lt;/span&gt; (&lt;span style="color: magenta;"&gt;1&lt;/span&gt;) {&lt;br /&gt;&lt;span style="color: brown;"&gt;15 &lt;/span&gt;    &lt;span style="color: brown;"&gt;&lt;b&gt;print&lt;/b&gt;&lt;/span&gt; &lt;span style="color: magenta;"&gt;"&lt;/span&gt;&lt;span style="color: magenta;"&gt;Listo&amp;gt; &lt;/span&gt;&lt;span style="color: magenta;"&gt;"&lt;/span&gt;;&lt;br /&gt;&lt;span style="color: brown;"&gt;16 &lt;/span&gt;    &lt;span style="color: brown;"&gt;&lt;b&gt;my&lt;/b&gt;&lt;/span&gt; &lt;span style="color: darkcyan;"&gt;$command&lt;/span&gt; = &lt;span style="color: brown;"&gt;&lt;b&gt;readline&lt;/b&gt;&lt;/span&gt;(&lt;span style="color: darkcyan;"&gt;STDIN&lt;/span&gt;) &lt;span style="color: brown;"&gt;&lt;b&gt;//&lt;/b&gt;&lt;/span&gt; &lt;span style="color: brown;"&gt;&lt;b&gt;last&lt;/b&gt;&lt;/span&gt;;&lt;br /&gt;&lt;span style="color: brown;"&gt;17 &lt;/span&gt;    &lt;span style="color: darkcyan;"&gt;$command&lt;/span&gt; =~ &lt;span style="color: brown;"&gt;&lt;b&gt;s/&lt;/b&gt;&lt;/span&gt;&lt;span style="color: magenta;"&gt;^&lt;/span&gt;&lt;span style="color: slateblue;"&gt;\s&lt;/span&gt;&lt;span style="color: slateblue;"&gt;+&lt;/span&gt;&lt;span style="color: brown;"&gt;&lt;b&gt;//&lt;/b&gt;&lt;/span&gt;;&lt;br /&gt;&lt;span style="color: brown;"&gt;18 &lt;/span&gt;    &lt;span style="color: darkcyan;"&gt;$command&lt;/span&gt; =~ &lt;span style="color: brown;"&gt;&lt;b&gt;s/&lt;/b&gt;&lt;/span&gt;&lt;span style="color: slateblue;"&gt;\s&lt;/span&gt;&lt;span style="color: slateblue;"&gt;+&lt;/span&gt;&lt;span style="color: magenta;"&gt;$&lt;/span&gt;&lt;span style="color: brown;"&gt;&lt;b&gt;//&lt;/b&gt;&lt;/span&gt;;&lt;br /&gt;&lt;span style="color: brown;"&gt;19 &lt;/span&gt;    given (&lt;span style="color: darkcyan;"&gt;$command&lt;/span&gt;) {&lt;br /&gt;&lt;span style="color: brown;"&gt;20 &lt;/span&gt;        when ( looks_like_number(&lt;span style="color: darkcyan;"&gt;$_&lt;/span&gt;) ) { &lt;span style="color: darkcyan;"&gt;$s&lt;/span&gt;&lt;span style="color: darkcyan;"&gt;-&amp;gt;add_data&lt;/span&gt;(&lt;span style="color: darkcyan;"&gt;$command&lt;/span&gt;) }&lt;br /&gt;&lt;span style="color: brown;"&gt;21 &lt;/span&gt;        when (&lt;span style="color: darkcyan;"&gt;%FUNCS&lt;/span&gt;)                  { say &lt;span style="color: magenta;"&gt;"&lt;/span&gt;&lt;span style="color: darkcyan;"&gt;$command&lt;/span&gt;&lt;span style="color: magenta;"&gt; = &lt;/span&gt;&lt;span style="color: magenta;"&gt;"&lt;/span&gt; . &lt;span style="color: darkcyan;"&gt;$s&lt;/span&gt;-&amp;gt;&lt;span style="color: darkcyan;"&gt;$command&lt;/span&gt; }&lt;br /&gt;&lt;span style="color: brown;"&gt;22 &lt;/span&gt;        when ( [ &lt;span style="color: magenta;"&gt;"&lt;/span&gt;&lt;span style="color: magenta;"&gt;exit&lt;/span&gt;&lt;span style="color: magenta;"&gt;"&lt;/span&gt;, &lt;span style="color: magenta;"&gt;"&lt;/span&gt;&lt;span style="color: magenta;"&gt;quit&lt;/span&gt;&lt;span style="color: magenta;"&gt;"&lt;/span&gt; ] )    {&lt;span style="color: brown;"&gt;&lt;b&gt;last&lt;/b&gt;&lt;/span&gt;}&lt;br /&gt;&lt;span style="color: brown;"&gt;23 &lt;/span&gt;        when (&lt;span style="color: magenta;"&gt;"&lt;/span&gt;&lt;span style="color: magenta;"&gt;help&lt;/span&gt;&lt;span style="color: magenta;"&gt;"&lt;/span&gt;) {&lt;br /&gt;&lt;span style="color: brown;"&gt;24 &lt;/span&gt;            say &lt;span style="color: magenta;"&gt;"&lt;/span&gt;&lt;span style="color: magenta;"&gt;Los comandos válidos son: &lt;/span&gt;&lt;span style="color: magenta;"&gt;"&lt;/span&gt;&lt;br /&gt;&lt;span style="color: brown;"&gt;25 &lt;/span&gt;                . &lt;span style="color: brown;"&gt;&lt;b&gt;join&lt;/b&gt;&lt;/span&gt;( &lt;span style="color: magenta;"&gt;"&lt;/span&gt;&lt;span style="color: magenta;"&gt;, &lt;/span&gt;&lt;span style="color: magenta;"&gt;"&lt;/span&gt;, &lt;span style="color: magenta;"&gt;qw(&lt;/span&gt;&lt;span style="color: magenta;"&gt;exit quit help&lt;/span&gt;&lt;span style="color: magenta;"&gt;)&lt;/span&gt;, &lt;span style="color: brown;"&gt;&lt;b&gt;keys&lt;/b&gt;&lt;/span&gt; &lt;span style="color: darkcyan;"&gt;%FUNCS&lt;/span&gt; )&lt;br /&gt;&lt;span style="color: brown;"&gt;26 &lt;/span&gt;        }&lt;br /&gt;&lt;span style="color: brown;"&gt;27 &lt;/span&gt;        default { say SYNTAX_ERROR };&lt;br /&gt;&lt;span style="color: brown;"&gt;28 &lt;/span&gt;    }&lt;br /&gt;&lt;span style="color: brown;"&gt;29 &lt;/span&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5238463735728501931-5776083786445760284?l=perliscopio.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://perliscopio.blogspot.com/feeds/5776083786445760284/comments/default' title='Enviar comentarios'/><link rel='replies' type='text/html' href='http://perliscopio.blogspot.com/2009/09/perl-inteligente.html#comment-form' title='1 comentarios'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5238463735728501931/posts/default/5776083786445760284'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5238463735728501931/posts/default/5776083786445760284'/><link rel='alternate' type='text/html' href='http://perliscopio.blogspot.com/2009/09/perl-inteligente.html' title='Perl inteligente'/><author><name>Jose Rey</name><uri>http://www.blogger.com/profile/15071755167581242815</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5238463735728501931.post-1813097255894330040</id><published>2009-09-16T18:06:00.001-04:30</published><updated>2009-09-17T01:55:27.326-04:30</updated><title type='text'>Perl en cinco oraciones</title><content type='html'>Generalmente cuando escribo promoviendo Perl, lo hago a la defensiva, porque el estigma que le tienen encima es como exagerado, sin embargo me encontre este &lt;a href="http://blog.timbunce.org/2009/09/10/perl-in-five-sentences/"&gt;artículo&lt;/a&gt; y no pude resistir la tentación de copiar las oraciones, porque estan muy buenas.&lt;br /&gt;&lt;br /&gt;Perl:&lt;br /&gt;&lt;ol&gt;&lt;li&gt;Tiene una librería gigantesca de código reutilizable&lt;/li&gt;&lt;li&gt;Tiene una cultura de mejores prácticas y pruebas de calidad&lt;/li&gt;&lt;li&gt;Tiene una comunidad en crecimiento en la que todo el mundo es bienvenido&lt;/li&gt;&lt;li&gt;Tanto Perl5 como Perl6 tienen un gran futuro.&lt;br /&gt;&lt;/li&gt;&lt;li&gt;Durante los últimos 20 años ha sido un gran lenguaje para terminar los trabajos rápidamente y lo seguirá siendo por los próximos 20 años&lt;br /&gt;&lt;/li&gt;&lt;/ol&gt;Voy a sacarle punta a ese resumen ;-)&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5238463735728501931-1813097255894330040?l=perliscopio.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://perliscopio.blogspot.com/feeds/1813097255894330040/comments/default' title='Enviar comentarios'/><link rel='replies' type='text/html' href='http://perliscopio.blogspot.com/2009/09/perl-en-cinco-oraciones.html#comment-form' title='0 comentarios'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5238463735728501931/posts/default/1813097255894330040'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5238463735728501931/posts/default/1813097255894330040'/><link rel='alternate' type='text/html' href='http://perliscopio.blogspot.com/2009/09/perl-en-cinco-oraciones.html' title='Perl en cinco oraciones'/><author><name>Jose Rey</name><uri>http://www.blogger.com/profile/15071755167581242815</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5238463735728501931.post-2255775563770191941</id><published>2009-09-15T14:37:00.004-04:30</published><updated>2009-09-18T09:36:28.675-04:30</updated><category scheme='http://www.blogger.com/atom/ns#' term='Tutorial'/><category scheme='http://www.blogger.com/atom/ns#' term='Perl'/><category scheme='http://www.blogger.com/atom/ns#' term='Estilo'/><category scheme='http://www.blogger.com/atom/ns#' term='Programación'/><title type='text'>Usando Perl Moderno</title><content type='html'>[&lt;a href="http://perliscope.blogspot.com/2009/09/using-modern-perl.html"&gt;English translation&lt;/a&gt;]&lt;br /&gt;Voy a intentar escribir una serie de artículos sobre Perl donde se pueda apreciar lo fácil y rápido que se pueden crear soluciones en esta plataforma.&lt;br /&gt;Para ello elegí un diseño simple que me permite ilustrar una cantidad de técnicas y mejores prácticas, con un algoritmo accesible para cualquier programador aunque sea novato.&lt;br /&gt;El programa de ejemplo será una calculadora estadística que en primera instancia utilizará un estilo tradicional, pero que se transformará poco a poco, haciéndose más flexible y fácil de mantener, mientras se aplican algunos mecanismos únicos del lenguaje y algunas librerías del &lt;a href="http://www.cpan.org/"&gt;CPAN&lt;/a&gt;.&lt;br /&gt;El gran final es hacer que la calculadora sea una aplicación web utilizando un mecanismo sorprendente desarrollado sobre Perl. Una vez dicho esto comenzaré a usar Perl Moderno.&lt;br /&gt;Haciendo honor al título del artículo, lo primero que hace nuestro programa es usar el módulo &lt;a href="http://search.cpan.org/perldoc?Modern%3A%3APerl"&gt;Modern::Perl&lt;/a&gt;, que es un atajo para decir:&lt;br /&gt;&lt;pre&gt;&lt;code&gt;&lt;br /&gt;use feature ':5.10';&lt;br /&gt;use strict;&lt;br /&gt;use warnings;&lt;br /&gt;use mro 'c3';&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;Es decir, activa todas las características introducidas en Perl 5.10, también activa el modo estricto y las advertencias, y finalmente activa el &lt;a href="http://search.cpan.org/perldoc?mro"&gt;orden de resolución de métodos&lt;/a&gt; utilizando el &lt;a href="http://www.worldlingo.com/ma/enwiki/es/C3_linearization/1"&gt;algoritmo C3&lt;/a&gt;. Como es de esperarse todos los ejemplos que veremos a lo largo de esta serie de artículos, solo funcionarán en Perl 5.10, porque intentare promover la mayor cantidad de características de esta nueva versión del lenguaje, así que: a &lt;a href="http://www.perl.org/get.html"&gt;instalar Perl 5.10&lt;/a&gt;.&lt;br /&gt;Al usar Perl Moderno, se recomienda enfáticamente el uso de &lt;code&gt;strict&lt;/code&gt; porque captura muchos errores comunes, entre ellos el uso accidental de referencias simbólicas, y los errores de tipográficos en las variables, al costo de que ahora deben ser declaradas con &lt;code&gt;our&lt;/code&gt; (globales) ó &lt;code&gt;my&lt;/code&gt; (léxicas), antes de usarse.&lt;br /&gt;Por otra parte las advertencias permiten que perl nos informe acerca de posibles errores en la codificación. En perl 5.10 &lt;code&gt;strict&lt;/code&gt; es más estricto y &lt;code&gt;warnings&lt;/code&gt; tiene muchas advertencias nuevas, así que capturan más problemas que antes, lo que suele mejorar la calidad general del código y ahorrar tiempo de depuración.&lt;br /&gt;En mi caso particular, cuando quise leer un comando y terminar el ciclo en caso de un fin de archivo escribí:&lt;br /&gt;&lt;pre&gt;&lt;code&gt;&lt;br /&gt;my $comando = readline(STDIN) or last;&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;Perl inmediatamente me advirtió que en algún caso podría confundirse &lt;code&gt;undef&lt;/code&gt;  (que denota el fin de archivo) con un "0" (cero), porque en perl &lt;code&gt;"0"&lt;/code&gt; y &lt;code&gt;undef&lt;/code&gt; se interpretan como falso. Una manera de escribir correctamente la instrucción sería:&lt;br /&gt;&lt;pre&gt;&lt;code&gt;&lt;br /&gt;defined (my $comando = readline(STDIN)) or last;&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;Pero aproveché para utilizar el nuevo operador &lt;code&gt;//&lt;/code&gt; (defined or), con el que puedo escribir simplemente:&lt;br /&gt;&lt;pre&gt;&lt;code&gt;&lt;br /&gt;my $comando = readline(STDIN) // last;&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;El &lt;a href="http://search.cpan.org/perldoc?mro"&gt;orden de resolución de métodos C3&lt;/a&gt;, resuelve algunos problemas existentes con el orden de resolución original de Perl, y lo recomendable es usarlo siempre en el nuevo código, esto no es del todo nuevo, hay módulos que usan este orden de resolución desde hace unos 4 años, solo que antes era un módulo del CPAN (&lt;a href="http://search.cpan.org/perldoc?Class%3A%3AC3"&gt;Class::C3&lt;/a&gt;) y ahora tiene soporte nativo en el lenguaje.&lt;br /&gt;Así que el primer consejo es usar Modern::Perl, porque activa una cantidad de características útiles y recomendadas de Perl.&lt;br /&gt;Volviendo al programa, lo siguiente después de usar Modern::Perl es importar la subrutina looks_like_number() de &lt;a href="http://search.cpan.org/perldoc?Scalar%3A%3AUtil"&gt;Scalar::Util&lt;/a&gt;, que además de ahorrarme el trabajo de escribir las expresiones regulares para reconocer números, ahorra una buena cantidad de pánico de los lectores que podrían bloquearse de solo ver &lt;a href="http://perldoc.perl.org/perlfaq4.html#How-do-I-determine-whether-a-scalar-is-a-number/whole/integer/float?"&gt;esas expresiones regulares&lt;/a&gt;.  &lt;br /&gt;El último módulo que se usa es el ingrediente principal de la calculadora, porque nunca pasó por mi mente escribir algoritmos de estadística, para eso existe el &lt;a href="http://www.cpan.org/"&gt;CPAN&lt;/a&gt;, que tiene de todo. En este caso usé &lt;a href="http://search.cpan.org/perldoc?Statistics%3A%3ADescriptive"&gt;Statistics::Descriptive&lt;/a&gt;, que sirve perfectamente a mi propósito.&lt;br /&gt;En la línea 7 se declara una &lt;a href="http://search.cpan.org/perldoc?constant"&gt;constante&lt;/a&gt; con un mensaje de error y en la 9 se define una variable con un &lt;a href="http://search.cpan.org/perldoc?perltoot"&gt;objeto&lt;/a&gt; de la clase &lt;code&gt;Statistics::Descriptive::Full&lt;/code&gt;, que será el estado de nuestra calculadora estádística, durante el ciclo de interpretación.&lt;br /&gt;El ciclo principal es simple: lee un comando o se termina (last) si llegó el fin de archivo [línea 12], seguidamente se eliminan  los espacios por la izquierda y la derecha del comando [línea 13], si el comando es un número se agrega al conjunto de datos del objeto  &lt;code&gt;Statistics::Descriptive::Full&lt;/code&gt; [línea 15] y si no, se selecciona y ejecuta un comando del interpretador.&lt;br /&gt;La selección se hace con la nueva estructura de control de Perl 5.10 &lt;a href="http://perldoc.perl.org/perlsyn.html#Switch-statements"&gt;given/when&lt;/a&gt; [líneas 18-36] que efectúa &lt;a href="http://perldoc.perl.org/perlsyn.html#Smart-matching-in-detail"&gt;smart matching&lt;/a&gt; entre el valor dado (given) y las clausulas de comparación (when). Como la comparación es "inteligente" depende de los operandos, y en general funciona como uno se lo imagina, sin embargo hay algunos casos rebuscados y nunca está de más &lt;a href="http://perldoc.perl.org/perlsyn.html#Switch-statements"&gt;leer los manuales&lt;/a&gt;.&lt;br /&gt;Finalmente el nuevo operador &lt;code&gt;say&lt;/code&gt;, que no es más que un &lt;code&gt;print&lt;/code&gt; que emite un fin de línea, ayudando a evitar un montón de concatenaciones con "\n" y por ello contribuye con la claridad del código.&lt;br /&gt;&lt;pre&gt;&lt;code&gt;&lt;br /&gt;&lt;span style="color: brown;"&gt; 1 &lt;/span&gt;&lt;span style="color: #a020f0;"&gt;#!/usr/bin/perl&lt;/span&gt;&lt;br /&gt;&lt;span style="color: brown;"&gt; 2 &lt;/span&gt;&lt;br /&gt;&lt;span style="color: brown;"&gt; 3 &lt;/span&gt;&lt;span style="color: #a020f0;"&gt;use &lt;/span&gt;Modern::Perl;&lt;br /&gt;&lt;span style="color: brown;"&gt; 4 &lt;/span&gt;&lt;span style="color: #a020f0;"&gt;use &lt;/span&gt;Scalar::Util &lt;span style="color: magenta;"&gt;qw(&lt;/span&gt;&lt;span style="color: magenta;"&gt; looks_like_number &lt;/span&gt;&lt;span style="color: magenta;"&gt;)&lt;/span&gt;;&lt;br /&gt;&lt;span style="color: brown;"&gt; 5 &lt;/span&gt;&lt;span style="color: #a020f0;"&gt;use &lt;/span&gt;Statistics::Descriptive;&lt;br /&gt;&lt;span style="color: brown;"&gt; 6 &lt;/span&gt;&lt;br /&gt;&lt;span style="color: brown;"&gt; 7 &lt;/span&gt;&lt;span style="color: #a020f0;"&gt;use constant&lt;/span&gt; &lt;span style="color: magenta;"&gt;SYNTAX_ERROR &lt;/span&gt;=&amp;gt; &lt;span style="color: magenta;"&gt;"&lt;/span&gt;&lt;span style="color: magenta;"&gt;Error: tipee 'help' para ayuda&lt;/span&gt;&lt;span style="color: magenta;"&gt;"&lt;/span&gt;;&lt;br /&gt;&lt;span style="color: brown;"&gt; 8 &lt;/span&gt;&lt;br /&gt;&lt;span style="color: brown;"&gt; 9 &lt;/span&gt;&lt;span style="color: brown;"&gt;&lt;b&gt;my&lt;/b&gt;&lt;/span&gt; &lt;span style="color: darkcyan;"&gt;$s&lt;/span&gt; = Statistics::Descriptive::Full-&amp;gt;&lt;span style="color: brown;"&gt;&lt;b&gt;new&lt;/b&gt;&lt;/span&gt;();&lt;br /&gt;&lt;span style="color: brown;"&gt;10 &lt;/span&gt;&lt;span style="color: brown;"&gt;&lt;b&gt;while&lt;/b&gt;&lt;/span&gt; (&lt;span style="color: magenta;"&gt;1&lt;/span&gt;) {&lt;br /&gt;&lt;span style="color: brown;"&gt;11 &lt;/span&gt;    &lt;span style="color: brown;"&gt;&lt;b&gt;print&lt;/b&gt;&lt;/span&gt; &lt;span style="color: magenta;"&gt;"&lt;/span&gt;&lt;span style="color: magenta;"&gt;Listo&amp;gt; &lt;/span&gt;&lt;span style="color: magenta;"&gt;"&lt;/span&gt;;&lt;br /&gt;&lt;span style="color: brown;"&gt;12 &lt;/span&gt;    &lt;span style="color: brown;"&gt;&lt;b&gt;my&lt;/b&gt;&lt;/span&gt; &lt;span style="color: darkcyan;"&gt;$command&lt;/span&gt; = &lt;span style="color: brown;"&gt;&lt;b&gt;readline&lt;/b&gt;&lt;/span&gt;(&lt;span style="color: darkcyan;"&gt;STDIN&lt;/span&gt;) &lt;span style="color: brown;"&gt;&lt;b&gt;//&lt;/b&gt;&lt;/span&gt; &lt;span style="color: brown;"&gt;&lt;b&gt;last&lt;/b&gt;&lt;/span&gt;;&lt;br /&gt;&lt;span style="color: brown;"&gt;13 &lt;/span&gt;    &lt;span style="color: darkcyan;"&gt;$command&lt;/span&gt; =~ &lt;span style="color: brown;"&gt;&lt;b&gt;s/&lt;/b&gt;&lt;/span&gt;&lt;span style="color: magenta;"&gt;^&lt;/span&gt;&lt;span style="color: slateblue;"&gt;\s&lt;/span&gt;&lt;span style="color: slateblue;"&gt;+&lt;/span&gt;&lt;span style="color: brown;"&gt;&lt;b&gt;//&lt;/b&gt;&lt;/span&gt;; &lt;span style="color: darkcyan;"&gt;$command&lt;/span&gt; =~ &lt;span style="color: brown;"&gt;&lt;b&gt;s/&lt;/b&gt;&lt;/span&gt;&lt;span style="color: slateblue;"&gt;\s&lt;/span&gt;&lt;span style="color: slateblue;"&gt;+&lt;/span&gt;&lt;span style="color: magenta;"&gt;$&lt;/span&gt;&lt;span style="color: brown;"&gt;&lt;b&gt;//&lt;/b&gt;&lt;/span&gt;;&lt;br /&gt;&lt;span style="color: brown;"&gt;14 &lt;/span&gt;    &lt;span style="color: brown;"&gt;&lt;b&gt;if&lt;/b&gt;&lt;/span&gt; ( looks_like_number(&lt;span style="color: darkcyan;"&gt;$command&lt;/span&gt;) ) {&lt;br /&gt;&lt;span style="color: brown;"&gt;15 &lt;/span&gt;        &lt;span style="color: darkcyan;"&gt;$s&lt;/span&gt;&lt;span style="color: darkcyan;"&gt;-&amp;gt;add_data&lt;/span&gt;(&lt;span style="color: darkcyan;"&gt;$command&lt;/span&gt;);&lt;br /&gt;&lt;span style="color: brown;"&gt;16 &lt;/span&gt;    }&lt;br /&gt;&lt;span style="color: brown;"&gt;17 &lt;/span&gt;    &lt;span style="color: brown;"&gt;&lt;b&gt;else&lt;/b&gt;&lt;/span&gt; {&lt;br /&gt;&lt;span style="color: brown;"&gt;18 &lt;/span&gt;        given (&lt;span style="color: darkcyan;"&gt;$command&lt;/span&gt;) {&lt;br /&gt;&lt;span style="color: brown;"&gt;19 &lt;/span&gt;            when (&lt;span style="color: magenta;"&gt;"&lt;/span&gt;&lt;span style="color: magenta;"&gt;sum&lt;/span&gt;&lt;span style="color: magenta;"&gt;"&lt;/span&gt;)                { say &lt;span style="color: magenta;"&gt;"&lt;/span&gt;&lt;span style="color: darkcyan;"&gt;$command&lt;/span&gt;&lt;span style="color: magenta;"&gt; = &lt;/span&gt;&lt;span style="color: magenta;"&gt;"&lt;/span&gt; . &lt;span style="color: darkcyan;"&gt;$s&lt;/span&gt;&lt;span style="color: darkcyan;"&gt;-&amp;gt;sum&lt;/span&gt;() }&lt;br /&gt;&lt;span style="color: brown;"&gt;20 &lt;/span&gt;            when (&lt;span style="color: magenta;"&gt;"&lt;/span&gt;&lt;span style="color: magenta;"&gt;mean&lt;/span&gt;&lt;span style="color: magenta;"&gt;"&lt;/span&gt;)               { say &lt;span style="color: magenta;"&gt;"&lt;/span&gt;&lt;span style="color: darkcyan;"&gt;$command&lt;/span&gt;&lt;span style="color: magenta;"&gt; = &lt;/span&gt;&lt;span style="color: magenta;"&gt;"&lt;/span&gt; . &lt;span style="color: darkcyan;"&gt;$s&lt;/span&gt;&lt;span style="color: darkcyan;"&gt;-&amp;gt;mean&lt;/span&gt;() }&lt;br /&gt;&lt;span style="color: brown;"&gt;21 &lt;/span&gt;            when (&lt;span style="color: magenta;"&gt;"&lt;/span&gt;&lt;span style="color: magenta;"&gt;count&lt;/span&gt;&lt;span style="color: magenta;"&gt;"&lt;/span&gt;)              { say &lt;span style="color: magenta;"&gt;"&lt;/span&gt;&lt;span style="color: darkcyan;"&gt;$command&lt;/span&gt;&lt;span style="color: magenta;"&gt; = &lt;/span&gt;&lt;span style="color: magenta;"&gt;"&lt;/span&gt; . &lt;span style="color: darkcyan;"&gt;$s&lt;/span&gt;&lt;span style="color: darkcyan;"&gt;-&amp;gt;count&lt;/span&gt;() }&lt;br /&gt;&lt;span style="color: brown;"&gt;22 &lt;/span&gt;            when (&lt;span style="color: magenta;"&gt;"&lt;/span&gt;&lt;span style="color: magenta;"&gt;variance&lt;/span&gt;&lt;span style="color: magenta;"&gt;"&lt;/span&gt;)           { say &lt;span style="color: magenta;"&gt;"&lt;/span&gt;&lt;span style="color: darkcyan;"&gt;$command&lt;/span&gt;&lt;span style="color: magenta;"&gt; = &lt;/span&gt;&lt;span style="color: magenta;"&gt;"&lt;/span&gt; . &lt;span style="color: darkcyan;"&gt;$s&lt;/span&gt;&lt;span style="color: darkcyan;"&gt;-&amp;gt;variance&lt;/span&gt;() }&lt;br /&gt;&lt;span style="color: brown;"&gt;23 &lt;/span&gt;            when (&lt;span style="color: magenta;"&gt;"&lt;/span&gt;&lt;span style="color: magenta;"&gt;standard_deviation&lt;/span&gt;&lt;span style="color: magenta;"&gt;"&lt;/span&gt;) { say &lt;span style="color: magenta;"&gt;"&lt;/span&gt;&lt;span style="color: darkcyan;"&gt;$command&lt;/span&gt;&lt;span style="color: magenta;"&gt; = &lt;/span&gt;&lt;span style="color: magenta;"&gt;"&lt;/span&gt; . &lt;span style="color: darkcyan;"&gt;$s&lt;/span&gt;&lt;span style="color: darkcyan;"&gt;-&amp;gt;standard_deviation&lt;/span&gt;() }&lt;br /&gt;&lt;span style="color: brown;"&gt;24 &lt;/span&gt;            when (&lt;span style="color: magenta;"&gt;"&lt;/span&gt;&lt;span style="color: magenta;"&gt;min&lt;/span&gt;&lt;span style="color: magenta;"&gt;"&lt;/span&gt;)                { say &lt;span style="color: magenta;"&gt;"&lt;/span&gt;&lt;span style="color: darkcyan;"&gt;$command&lt;/span&gt;&lt;span style="color: magenta;"&gt; = &lt;/span&gt;&lt;span style="color: magenta;"&gt;"&lt;/span&gt; . &lt;span style="color: darkcyan;"&gt;$s&lt;/span&gt;&lt;span style="color: darkcyan;"&gt;-&amp;gt;min&lt;/span&gt;() }&lt;br /&gt;&lt;span style="color: brown;"&gt;25 &lt;/span&gt;            when (&lt;span style="color: magenta;"&gt;"&lt;/span&gt;&lt;span style="color: magenta;"&gt;mindex&lt;/span&gt;&lt;span style="color: magenta;"&gt;"&lt;/span&gt;)             { say &lt;span style="color: magenta;"&gt;"&lt;/span&gt;&lt;span style="color: darkcyan;"&gt;$command&lt;/span&gt;&lt;span style="color: magenta;"&gt; = &lt;/span&gt;&lt;span style="color: magenta;"&gt;"&lt;/span&gt; . &lt;span style="color: darkcyan;"&gt;$s&lt;/span&gt;&lt;span style="color: darkcyan;"&gt;-&amp;gt;mindex&lt;/span&gt;() }&lt;br /&gt;&lt;span style="color: brown;"&gt;26 &lt;/span&gt;            when (&lt;span style="color: magenta;"&gt;"&lt;/span&gt;&lt;span style="color: magenta;"&gt;max&lt;/span&gt;&lt;span style="color: magenta;"&gt;"&lt;/span&gt;)                { say &lt;span style="color: magenta;"&gt;"&lt;/span&gt;&lt;span style="color: darkcyan;"&gt;$command&lt;/span&gt;&lt;span style="color: magenta;"&gt; = &lt;/span&gt;&lt;span style="color: magenta;"&gt;"&lt;/span&gt; . &lt;span style="color: darkcyan;"&gt;$s&lt;/span&gt;&lt;span style="color: darkcyan;"&gt;-&amp;gt;max&lt;/span&gt;() }&lt;br /&gt;&lt;span style="color: brown;"&gt;27 &lt;/span&gt;            when (&lt;span style="color: magenta;"&gt;"&lt;/span&gt;&lt;span style="color: magenta;"&gt;maxdex&lt;/span&gt;&lt;span style="color: magenta;"&gt;"&lt;/span&gt;)             { say &lt;span style="color: magenta;"&gt;"&lt;/span&gt;&lt;span style="color: darkcyan;"&gt;$command&lt;/span&gt;&lt;span style="color: magenta;"&gt; = &lt;/span&gt;&lt;span style="color: magenta;"&gt;"&lt;/span&gt; . &lt;span style="color: darkcyan;"&gt;$s&lt;/span&gt;&lt;span style="color: darkcyan;"&gt;-&amp;gt;maxdex&lt;/span&gt;() }&lt;br /&gt;&lt;span style="color: brown;"&gt;28 &lt;/span&gt;            when (&lt;span style="color: magenta;"&gt;"&lt;/span&gt;&lt;span style="color: magenta;"&gt;sample_range&lt;/span&gt;&lt;span style="color: magenta;"&gt;"&lt;/span&gt;)       { say &lt;span style="color: magenta;"&gt;"&lt;/span&gt;&lt;span style="color: darkcyan;"&gt;$command&lt;/span&gt;&lt;span style="color: magenta;"&gt; = &lt;/span&gt;&lt;span style="color: magenta;"&gt;"&lt;/span&gt; . &lt;span style="color: darkcyan;"&gt;$s&lt;/span&gt;&lt;span style="color: darkcyan;"&gt;-&amp;gt;sample_range&lt;/span&gt;() }&lt;br /&gt;&lt;span style="color: brown;"&gt;29 &lt;/span&gt;            when (&lt;span style="color: magenta;"&gt;"&lt;/span&gt;&lt;span style="color: magenta;"&gt;median&lt;/span&gt;&lt;span style="color: magenta;"&gt;"&lt;/span&gt;)             { say &lt;span style="color: magenta;"&gt;"&lt;/span&gt;&lt;span style="color: darkcyan;"&gt;$command&lt;/span&gt;&lt;span style="color: magenta;"&gt; = &lt;/span&gt;&lt;span style="color: magenta;"&gt;"&lt;/span&gt; . &lt;span style="color: darkcyan;"&gt;$s&lt;/span&gt;&lt;span style="color: darkcyan;"&gt;-&amp;gt;median&lt;/span&gt;() }&lt;br /&gt;&lt;span style="color: brown;"&gt;30 &lt;/span&gt;            when (&lt;span style="color: magenta;"&gt;"&lt;/span&gt;&lt;span style="color: magenta;"&gt;harmonic_mean&lt;/span&gt;&lt;span style="color: magenta;"&gt;"&lt;/span&gt;)      { say &lt;span style="color: magenta;"&gt;"&lt;/span&gt;&lt;span style="color: darkcyan;"&gt;$command&lt;/span&gt;&lt;span style="color: magenta;"&gt; = &lt;/span&gt;&lt;span style="color: magenta;"&gt;"&lt;/span&gt; . &lt;span style="color: darkcyan;"&gt;$s&lt;/span&gt;&lt;span style="color: darkcyan;"&gt;-&amp;gt;harmonic_mean&lt;/span&gt;() }&lt;br /&gt;&lt;span style="color: brown;"&gt;31 &lt;/span&gt;            when (&lt;span style="color: magenta;"&gt;"&lt;/span&gt;&lt;span style="color: magenta;"&gt;geometric_mean&lt;/span&gt;&lt;span style="color: magenta;"&gt;"&lt;/span&gt;)     { say &lt;span style="color: magenta;"&gt;"&lt;/span&gt;&lt;span style="color: darkcyan;"&gt;$command&lt;/span&gt;&lt;span style="color: magenta;"&gt; = &lt;/span&gt;&lt;span style="color: magenta;"&gt;"&lt;/span&gt; . &lt;span style="color: darkcyan;"&gt;$s&lt;/span&gt;&lt;span style="color: darkcyan;"&gt;-&amp;gt;geometric_mean&lt;/span&gt;() }&lt;br /&gt;&lt;span style="color: brown;"&gt;32 &lt;/span&gt;            when (&lt;span style="color: magenta;"&gt;"&lt;/span&gt;&lt;span style="color: magenta;"&gt;mode&lt;/span&gt;&lt;span style="color: magenta;"&gt;"&lt;/span&gt;)               { say &lt;span style="color: magenta;"&gt;"&lt;/span&gt;&lt;span style="color: darkcyan;"&gt;$command&lt;/span&gt;&lt;span style="color: magenta;"&gt; = &lt;/span&gt;&lt;span style="color: magenta;"&gt;"&lt;/span&gt; . &lt;span style="color: darkcyan;"&gt;$s&lt;/span&gt;&lt;span style="color: darkcyan;"&gt;-&amp;gt;mode&lt;/span&gt;() }&lt;br /&gt;&lt;span style="color: brown;"&gt;33 &lt;/span&gt;            when (&lt;span style="color: magenta;"&gt;"&lt;/span&gt;&lt;span style="color: magenta;"&gt;trimmed_mean&lt;/span&gt;&lt;span style="color: magenta;"&gt;"&lt;/span&gt;)       { say &lt;span style="color: magenta;"&gt;"&lt;/span&gt;&lt;span style="color: darkcyan;"&gt;$command&lt;/span&gt;&lt;span style="color: magenta;"&gt; = &lt;/span&gt;&lt;span style="color: magenta;"&gt;"&lt;/span&gt; . &lt;span style="color: darkcyan;"&gt;$s&lt;/span&gt;&lt;span style="color: darkcyan;"&gt;-&amp;gt;trimmed_mean&lt;/span&gt;() }&lt;br /&gt;&lt;span style="color: brown;"&gt;34 &lt;/span&gt;            when (&lt;span style="color: brown;"&gt;&lt;b&gt;/&lt;/b&gt;&lt;/span&gt;&lt;span style="color: magenta;"&gt;^&lt;/span&gt;&lt;span style="color: slateblue;"&gt;(&lt;/span&gt;&lt;span style="color: magenta;"&gt;exit|quit&lt;/span&gt;&lt;span style="color: slateblue;"&gt;)&lt;/span&gt;&lt;span style="color: magenta;"&gt;$&lt;/span&gt;&lt;span style="color: brown;"&gt;&lt;b&gt;/&lt;/b&gt;&lt;/span&gt;)      {&lt;span style="color: brown;"&gt;&lt;b&gt;last&lt;/b&gt;&lt;/span&gt;}&lt;br /&gt;&lt;span style="color: brown;"&gt;35 &lt;/span&gt;            default                     { say SYNTAX_ERROR }&lt;br /&gt;&lt;span style="color: brown;"&gt;36 &lt;/span&gt;        }&lt;br /&gt;&lt;span style="color: brown;"&gt;37 &lt;/span&gt;    }&lt;br /&gt;&lt;span style="color: brown;"&gt;38 &lt;/span&gt;}&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;Para usar la calculadora simplemente ejecutamos el archivo, aquí les muestro una corrida de prueba:&lt;br /&gt;&lt;pre&gt;&lt;code&gt;&lt;br /&gt;opr@toshi$ perl stat.pl&lt;/code&gt;&lt;/pre&gt;&lt;pre&gt;&lt;code&gt;Listo&amp;gt; 19&lt;br /&gt;Listo&amp;gt; 45&lt;br /&gt;Listo&amp;gt; 24&lt;br /&gt;Listo&amp;gt; 15&lt;br /&gt;Listo&amp;gt; 39&lt;br /&gt;Listo&amp;gt; 48&lt;br /&gt;Listo&amp;gt; 36&lt;br /&gt;Listo&amp;gt; count&lt;br /&gt;count = 7&lt;br /&gt;Listo&amp;gt; 10&lt;br /&gt;Listo&amp;gt; 28&lt;br /&gt;Listo&amp;gt; 30&lt;br /&gt;Listo&amp;gt; count&lt;br /&gt;count = 10&lt;br /&gt;Listo&amp;gt; mean&lt;br /&gt;mean = 29.4&lt;br /&gt;Listo&amp;gt; standard_deviation&lt;br /&gt;standard_deviation = 12.685950233756&lt;br /&gt;Listo&amp;gt; salir&lt;br /&gt;Error: tipee 'help' para ayuda&lt;br /&gt;Listo&amp;gt; help&lt;br /&gt;Error: tipee 'help' para ayuda&lt;br /&gt;Listo&amp;gt; exit&lt;br /&gt;opr@toshi$&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;h2&gt;Una mejora sencilla&lt;/h2&gt;Una mejora de estilo podría ser eliminar el &lt;code&gt;if&lt;/code&gt; de la línea 15 y hacer la comparación en el &lt;code&gt;given&lt;/code&gt;, esto además me permite mostrar que &lt;code&gt;given&lt;/code&gt; topicaliza &lt;code&gt;$_&lt;/code&gt; al valor dado y que las clausulas &lt;code&gt;when&lt;/code&gt; no solo comparan cadenas (usando &lt;code&gt;eq&lt;/code&gt;) y expresiones regulares (usando &lt;code&gt;=~&lt;/code&gt;), sino que permiten, &lt;a href="http://perldoc.perl.org/perlsyn.html#Switch-statements"&gt;entre otros&lt;/a&gt;, escribir expresiones booleanas utilizando &lt;code&gt;$_&lt;/code&gt; como un alias al valor dado en el &lt;code&gt;given&lt;/code&gt;.&lt;br /&gt;&lt;pre&gt;&lt;code&gt;&lt;br /&gt;&lt;span style="color: brown;"&gt; 1 &lt;/span&gt;&lt;span style="color: #a020f0;"&gt;#!/usr/bin/perl&lt;/span&gt;&lt;br /&gt;&lt;span style="color: brown;"&gt; 2 &lt;/span&gt;&lt;br /&gt;&lt;span style="color: brown;"&gt; 3 &lt;/span&gt;&lt;span style="color: #a020f0;"&gt;use &lt;/span&gt;Modern::Perl;&lt;br /&gt;&lt;span style="color: brown;"&gt; 4 &lt;/span&gt;&lt;span style="color: #a020f0;"&gt;use &lt;/span&gt;Scalar::Util &lt;span style="color: magenta;"&gt;qw(&lt;/span&gt;&lt;span style="color: magenta;"&gt; looks_like_number &lt;/span&gt;&lt;span style="color: magenta;"&gt;)&lt;/span&gt;;&lt;br /&gt;&lt;span style="color: brown;"&gt; 5 &lt;/span&gt;&lt;span style="color: #a020f0;"&gt;use &lt;/span&gt;Statistics::Descriptive;&lt;br /&gt;&lt;span style="color: brown;"&gt; 6 &lt;/span&gt;&lt;br /&gt;&lt;span style="color: brown;"&gt; 7 &lt;/span&gt;&lt;span style="color: #a020f0;"&gt;use constant&lt;/span&gt; &lt;span style="color: magenta;"&gt;SYNTAX_ERROR &lt;/span&gt;=&amp;gt; &lt;span style="color: magenta;"&gt;"&lt;/span&gt;&lt;span style="color: magenta;"&gt;Error: tipee 'help' para ayuda&lt;/span&gt;&lt;span style="color: magenta;"&gt;"&lt;/span&gt;;&lt;br /&gt;&lt;span style="color: brown;"&gt; 8 &lt;/span&gt;&lt;br /&gt;&lt;span style="color: brown;"&gt; 9 &lt;/span&gt;&lt;span style="color: brown;"&gt;&lt;b&gt;my&lt;/b&gt;&lt;/span&gt; &lt;span style="color: darkcyan;"&gt;$s&lt;/span&gt; = Statistics::Descriptive::Full-&amp;gt;&lt;span style="color: brown;"&gt;&lt;b&gt;new&lt;/b&gt;&lt;/span&gt;();&lt;br /&gt;&lt;span style="color: brown;"&gt;10 &lt;/span&gt;&lt;span style="color: brown;"&gt;&lt;b&gt;while&lt;/b&gt;&lt;/span&gt; (&lt;span style="color: magenta;"&gt;1&lt;/span&gt;) {&lt;br /&gt;&lt;span style="color: brown;"&gt;11 &lt;/span&gt;    &lt;span style="color: brown;"&gt;&lt;b&gt;print&lt;/b&gt;&lt;/span&gt; &lt;span style="color: magenta;"&gt;"&lt;/span&gt;&lt;span style="color: magenta;"&gt;Listo&amp;gt; &lt;/span&gt;&lt;span style="color: magenta;"&gt;"&lt;/span&gt;;&lt;br /&gt;&lt;span style="color: brown;"&gt;12 &lt;/span&gt;    &lt;span style="color: brown;"&gt;&lt;b&gt;my&lt;/b&gt;&lt;/span&gt; &lt;span style="color: darkcyan;"&gt;$command&lt;/span&gt; = &lt;span style="color: brown;"&gt;&lt;b&gt;readline&lt;/b&gt;&lt;/span&gt;(&lt;span style="color: darkcyan;"&gt;STDIN&lt;/span&gt;) &lt;span style="color: brown;"&gt;&lt;b&gt;//&lt;/b&gt;&lt;/span&gt; &lt;span style="color: brown;"&gt;&lt;b&gt;last&lt;/b&gt;&lt;/span&gt;;&lt;br /&gt;&lt;span style="color: brown;"&gt;13 &lt;/span&gt;    &lt;span style="color: darkcyan;"&gt;$command&lt;/span&gt; =~ &lt;span style="color: brown;"&gt;&lt;b&gt;s/&lt;/b&gt;&lt;/span&gt;&lt;span style="color: magenta;"&gt;^&lt;/span&gt;&lt;span style="color: slateblue;"&gt;\s&lt;/span&gt;&lt;span style="color: slateblue;"&gt;+&lt;/span&gt;&lt;span style="color: brown;"&gt;&lt;b&gt;//&lt;/b&gt;&lt;/span&gt;; &lt;span style="color: darkcyan;"&gt;$command&lt;/span&gt; =~ &lt;span style="color: brown;"&gt;&lt;b&gt;s/&lt;/b&gt;&lt;/span&gt;&lt;span style="color: slateblue;"&gt;\s&lt;/span&gt;&lt;span style="color: slateblue;"&gt;+&lt;/span&gt;&lt;span style="color: magenta;"&gt;$&lt;/span&gt;&lt;span style="color: brown;"&gt;&lt;b&gt;//&lt;/b&gt;&lt;/span&gt;;&lt;br /&gt;&lt;span style="color: brown;"&gt;14 &lt;/span&gt;    given (&lt;span style="color: darkcyan;"&gt;$command&lt;/span&gt;) {&lt;br /&gt;&lt;span style="color: brown;"&gt;15 &lt;/span&gt;        when ( looks_like_number(&lt;span style="color: darkcyan;"&gt;$_&lt;/span&gt;) ) { &lt;span style="color: darkcyan;"&gt;$s&lt;/span&gt;&lt;span style="color: darkcyan;"&gt;-&amp;gt;add_data&lt;/span&gt;(&lt;span style="color: darkcyan;"&gt;$command&lt;/span&gt;) }&lt;br /&gt;&lt;span style="color: brown;"&gt;16 &lt;/span&gt;        when (&lt;span style="color: magenta;"&gt;"&lt;/span&gt;&lt;span style="color: magenta;"&gt;sum&lt;/span&gt;&lt;span style="color: magenta;"&gt;"&lt;/span&gt;)                   { say &lt;span style="color: magenta;"&gt;"&lt;/span&gt;&lt;span style="color: darkcyan;"&gt;$command&lt;/span&gt;&lt;span style="color: magenta;"&gt; = &lt;/span&gt;&lt;span style="color: magenta;"&gt;"&lt;/span&gt; . &lt;span style="color: darkcyan;"&gt;$s&lt;/span&gt;&lt;span style="color: darkcyan;"&gt;-&amp;gt;sum&lt;/span&gt;() }&lt;br /&gt;&lt;span style="color: brown;"&gt;17 &lt;/span&gt;        when (&lt;span style="color: magenta;"&gt;"&lt;/span&gt;&lt;span style="color: magenta;"&gt;mean&lt;/span&gt;&lt;span style="color: magenta;"&gt;"&lt;/span&gt;)                  { say &lt;span style="color: magenta;"&gt;"&lt;/span&gt;&lt;span style="color: darkcyan;"&gt;$command&lt;/span&gt;&lt;span style="color: magenta;"&gt; = &lt;/span&gt;&lt;span style="color: magenta;"&gt;"&lt;/span&gt; . &lt;span style="color: darkcyan;"&gt;$s&lt;/span&gt;&lt;span style="color: darkcyan;"&gt;-&amp;gt;mean&lt;/span&gt;() }&lt;br /&gt;&lt;span style="color: brown;"&gt;18 &lt;/span&gt;        when (&lt;span style="color: magenta;"&gt;"&lt;/span&gt;&lt;span style="color: magenta;"&gt;count&lt;/span&gt;&lt;span style="color: magenta;"&gt;"&lt;/span&gt;)                 { say &lt;span style="color: magenta;"&gt;"&lt;/span&gt;&lt;span style="color: darkcyan;"&gt;$command&lt;/span&gt;&lt;span style="color: magenta;"&gt; = &lt;/span&gt;&lt;span style="color: magenta;"&gt;"&lt;/span&gt; . &lt;span style="color: darkcyan;"&gt;$s&lt;/span&gt;&lt;span style="color: darkcyan;"&gt;-&amp;gt;count&lt;/span&gt;() }&lt;br /&gt;&lt;span style="color: brown;"&gt;19 &lt;/span&gt;        when (&lt;span style="color: magenta;"&gt;"&lt;/span&gt;&lt;span style="color: magenta;"&gt;variance&lt;/span&gt;&lt;span style="color: magenta;"&gt;"&lt;/span&gt;)              { say &lt;span style="color: magenta;"&gt;"&lt;/span&gt;&lt;span style="color: darkcyan;"&gt;$command&lt;/span&gt;&lt;span style="color: magenta;"&gt; = &lt;/span&gt;&lt;span style="color: magenta;"&gt;"&lt;/span&gt; . &lt;span style="color: darkcyan;"&gt;$s&lt;/span&gt;&lt;span style="color: darkcyan;"&gt;-&amp;gt;variance&lt;/span&gt;() }&lt;br /&gt;&lt;span style="color: brown;"&gt;20 &lt;/span&gt;        when (&lt;span style="color: magenta;"&gt;"&lt;/span&gt;&lt;span style="color: magenta;"&gt;standard_deviation&lt;/span&gt;&lt;span style="color: magenta;"&gt;"&lt;/span&gt;)    { say &lt;span style="color: magenta;"&gt;"&lt;/span&gt;&lt;span style="color: darkcyan;"&gt;$command&lt;/span&gt;&lt;span style="color: magenta;"&gt; = &lt;/span&gt;&lt;span style="color: magenta;"&gt;"&lt;/span&gt; . &lt;span style="color: darkcyan;"&gt;$s&lt;/span&gt;&lt;span style="color: darkcyan;"&gt;-&amp;gt;standard_deviation&lt;/span&gt;() }&lt;br /&gt;&lt;span style="color: brown;"&gt;21 &lt;/span&gt;        when (&lt;span style="color: magenta;"&gt;"&lt;/span&gt;&lt;span style="color: magenta;"&gt;min&lt;/span&gt;&lt;span style="color: magenta;"&gt;"&lt;/span&gt;)                   { say &lt;span style="color: magenta;"&gt;"&lt;/span&gt;&lt;span style="color: darkcyan;"&gt;$command&lt;/span&gt;&lt;span style="color: magenta;"&gt; = &lt;/span&gt;&lt;span style="color: magenta;"&gt;"&lt;/span&gt; . &lt;span style="color: darkcyan;"&gt;$s&lt;/span&gt;&lt;span style="color: darkcyan;"&gt;-&amp;gt;min&lt;/span&gt;() }&lt;br /&gt;&lt;span style="color: brown;"&gt;22 &lt;/span&gt;        when (&lt;span style="color: magenta;"&gt;"&lt;/span&gt;&lt;span style="color: magenta;"&gt;mindex&lt;/span&gt;&lt;span style="color: magenta;"&gt;"&lt;/span&gt;)                { say &lt;span style="color: magenta;"&gt;"&lt;/span&gt;&lt;span style="color: darkcyan;"&gt;$command&lt;/span&gt;&lt;span style="color: magenta;"&gt; = &lt;/span&gt;&lt;span style="color: magenta;"&gt;"&lt;/span&gt; . &lt;span style="color: darkcyan;"&gt;$s&lt;/span&gt;&lt;span style="color: darkcyan;"&gt;-&amp;gt;mindex&lt;/span&gt;() }&lt;br /&gt;&lt;span style="color: brown;"&gt;23 &lt;/span&gt;        when (&lt;span style="color: magenta;"&gt;"&lt;/span&gt;&lt;span style="color: magenta;"&gt;max&lt;/span&gt;&lt;span style="color: magenta;"&gt;"&lt;/span&gt;)                   { say &lt;span style="color: magenta;"&gt;"&lt;/span&gt;&lt;span style="color: darkcyan;"&gt;$command&lt;/span&gt;&lt;span style="color: magenta;"&gt; = &lt;/span&gt;&lt;span style="color: magenta;"&gt;"&lt;/span&gt; . &lt;span style="color: darkcyan;"&gt;$s&lt;/span&gt;&lt;span style="color: darkcyan;"&gt;-&amp;gt;max&lt;/span&gt;() }&lt;br /&gt;&lt;span style="color: brown;"&gt;24 &lt;/span&gt;        when (&lt;span style="color: magenta;"&gt;"&lt;/span&gt;&lt;span style="color: magenta;"&gt;maxdex&lt;/span&gt;&lt;span style="color: magenta;"&gt;"&lt;/span&gt;)                { say &lt;span style="color: magenta;"&gt;"&lt;/span&gt;&lt;span style="color: darkcyan;"&gt;$command&lt;/span&gt;&lt;span style="color: magenta;"&gt; = &lt;/span&gt;&lt;span style="color: magenta;"&gt;"&lt;/span&gt; . &lt;span style="color: darkcyan;"&gt;$s&lt;/span&gt;&lt;span style="color: darkcyan;"&gt;-&amp;gt;maxdex&lt;/span&gt;() }&lt;br /&gt;&lt;span style="color: brown;"&gt;25 &lt;/span&gt;        when (&lt;span style="color: magenta;"&gt;"&lt;/span&gt;&lt;span style="color: magenta;"&gt;sample_range&lt;/span&gt;&lt;span style="color: magenta;"&gt;"&lt;/span&gt;)          { say &lt;span style="color: magenta;"&gt;"&lt;/span&gt;&lt;span style="color: darkcyan;"&gt;$command&lt;/span&gt;&lt;span style="color: magenta;"&gt; = &lt;/span&gt;&lt;span style="color: magenta;"&gt;"&lt;/span&gt; . &lt;span style="color: darkcyan;"&gt;$s&lt;/span&gt;&lt;span style="color: darkcyan;"&gt;-&amp;gt;sample_range&lt;/span&gt;() }&lt;br /&gt;&lt;span style="color: brown;"&gt;26 &lt;/span&gt;        when (&lt;span style="color: magenta;"&gt;"&lt;/span&gt;&lt;span style="color: magenta;"&gt;median&lt;/span&gt;&lt;span style="color: magenta;"&gt;"&lt;/span&gt;)                { say &lt;span style="color: magenta;"&gt;"&lt;/span&gt;&lt;span style="color: darkcyan;"&gt;$command&lt;/span&gt;&lt;span style="color: magenta;"&gt; = &lt;/span&gt;&lt;span style="color: magenta;"&gt;"&lt;/span&gt; . &lt;span style="color: darkcyan;"&gt;$s&lt;/span&gt;&lt;span style="color: darkcyan;"&gt;-&amp;gt;median&lt;/span&gt;() }&lt;br /&gt;&lt;span style="color: brown;"&gt;27 &lt;/span&gt;        when (&lt;span style="color: magenta;"&gt;"&lt;/span&gt;&lt;span style="color: magenta;"&gt;harmonic_mean&lt;/span&gt;&lt;span style="color: magenta;"&gt;"&lt;/span&gt;)         { say &lt;span style="color: magenta;"&gt;"&lt;/span&gt;&lt;span style="color: darkcyan;"&gt;$command&lt;/span&gt;&lt;span style="color: magenta;"&gt; = &lt;/span&gt;&lt;span style="color: magenta;"&gt;"&lt;/span&gt; . &lt;span style="color: darkcyan;"&gt;$s&lt;/span&gt;&lt;span style="color: darkcyan;"&gt;-&amp;gt;harmonic_mean&lt;/span&gt;() }&lt;br /&gt;&lt;span style="color: brown;"&gt;28 &lt;/span&gt;        when (&lt;span style="color: magenta;"&gt;"&lt;/span&gt;&lt;span style="color: magenta;"&gt;geometric_mean&lt;/span&gt;&lt;span style="color: magenta;"&gt;"&lt;/span&gt;)        { say &lt;span style="color: magenta;"&gt;"&lt;/span&gt;&lt;span style="color: darkcyan;"&gt;$command&lt;/span&gt;&lt;span style="color: magenta;"&gt; = &lt;/span&gt;&lt;span style="color: magenta;"&gt;"&lt;/span&gt; . &lt;span style="color: darkcyan;"&gt;$s&lt;/span&gt;&lt;span style="color: darkcyan;"&gt;-&amp;gt;geometric_mean&lt;/span&gt;() }&lt;br /&gt;&lt;span style="color: brown;"&gt;29 &lt;/span&gt;        when (&lt;span style="color: magenta;"&gt;"&lt;/span&gt;&lt;span style="color: magenta;"&gt;mode&lt;/span&gt;&lt;span style="color: magenta;"&gt;"&lt;/span&gt;)                  { say &lt;span style="color: magenta;"&gt;"&lt;/span&gt;&lt;span style="color: darkcyan;"&gt;$command&lt;/span&gt;&lt;span style="color: magenta;"&gt; = &lt;/span&gt;&lt;span style="color: magenta;"&gt;"&lt;/span&gt; . &lt;span style="color: darkcyan;"&gt;$s&lt;/span&gt;&lt;span style="color: darkcyan;"&gt;-&amp;gt;mode&lt;/span&gt;() }&lt;br /&gt;&lt;span style="color: brown;"&gt;30 &lt;/span&gt;        when (&lt;span style="color: magenta;"&gt;"&lt;/span&gt;&lt;span style="color: magenta;"&gt;trimmed_mean&lt;/span&gt;&lt;span style="color: magenta;"&gt;"&lt;/span&gt;)          { say &lt;span style="color: magenta;"&gt;"&lt;/span&gt;&lt;span style="color: darkcyan;"&gt;$command&lt;/span&gt;&lt;span style="color: magenta;"&gt; = &lt;/span&gt;&lt;span style="color: magenta;"&gt;"&lt;/span&gt; . &lt;span style="color: darkcyan;"&gt;$s&lt;/span&gt;&lt;span style="color: darkcyan;"&gt;-&amp;gt;trimmed_mean&lt;/span&gt;() }&lt;br /&gt;&lt;span style="color: brown;"&gt;31 &lt;/span&gt;        when (&lt;span style="color: brown;"&gt;&lt;b&gt;/&lt;/b&gt;&lt;/span&gt;&lt;span style="color: magenta;"&gt;^&lt;/span&gt;&lt;span style="color: slateblue;"&gt;(&lt;/span&gt;&lt;span style="color: magenta;"&gt;exit|quit&lt;/span&gt;&lt;span style="color: slateblue;"&gt;)&lt;/span&gt;&lt;span style="color: magenta;"&gt;$&lt;/span&gt;&lt;span style="color: brown;"&gt;&lt;b&gt;/&lt;/b&gt;&lt;/span&gt;)         {&lt;span style="color: brown;"&gt;&lt;b&gt;last&lt;/b&gt;&lt;/span&gt;}&lt;br /&gt;&lt;span style="color: brown;"&gt;32 &lt;/span&gt;        default                        { say SYNTAX_ERROR }&lt;br /&gt;&lt;span style="color: brown;"&gt;33 &lt;/span&gt;    }&lt;br /&gt;&lt;span style="color: brown;"&gt;34 &lt;/span&gt;}&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;Pienso que casi cualquier programador habituado a lenguajes dinámicos como Python o Ruby puede comprender sin dificultad código en Perl Moderno y sentirse cómodo trabajando con este.&lt;br /&gt;Los programadores de lenguajes como C, C++,C# o Java, después de adaptarse a algunos conceptos deberían sentir una especie de experiencia liberadora, porque seguramente en cualquiera de ellos cuesta mucho más escribir un programa como este.&lt;br /&gt;En el &lt;a href="http://perliscopio.blogspot.com/2009/09/perl-inteligente.html"&gt;próximo artículo&lt;/a&gt; veremos algunas características dinámicas de Perl, que hacen el programa más corto, flexible y fácil de mantener.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5238463735728501931-2255775563770191941?l=perliscopio.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://perliscopio.blogspot.com/feeds/2255775563770191941/comments/default' title='Enviar comentarios'/><link rel='replies' type='text/html' href='http://perliscopio.blogspot.com/2009/09/usando-perl-moderno.html#comment-form' title='7 comentarios'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5238463735728501931/posts/default/2255775563770191941'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5238463735728501931/posts/default/2255775563770191941'/><link rel='alternate' type='text/html' href='http://perliscopio.blogspot.com/2009/09/usando-perl-moderno.html' title='Usando Perl Moderno'/><author><name>Jose Rey</name><uri>http://www.blogger.com/profile/15071755167581242815</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>7</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5238463735728501931.post-3268827210871305081</id><published>2009-09-08T20:59:00.002-04:30</published><updated>2009-09-14T19:37:34.752-04:30</updated><category scheme='http://www.blogger.com/atom/ns#' term='Web'/><category scheme='http://www.blogger.com/atom/ns#' term='Comunidad'/><title type='text'>Los Perleros no usan IE</title><content type='html'>Divertida conclusión de las estadísticas que me da &lt;a href="http://www.google.com/analytics"&gt;Google&lt;br /&gt;Analytics&lt;/a&gt;, aunque más 33% de los visitantes del blog, utilizan&lt;br /&gt;Windows como sistema operativo, solo el 7% llega navegando con IE,&lt;br /&gt;a continuación las estadísticas.&lt;br /&gt;&lt;br /&gt;Sistemas Operativos&lt;br /&gt;&lt;br /&gt;&lt;table style="width: 20em;"&gt;&lt;thead&gt;&lt;tr&gt;     &lt;td&gt;Pos&lt;/td&gt;     &lt;td&gt;Sistema&lt;/td&gt;     &lt;td&gt;Rata&lt;/td&gt;   &lt;/tr&gt;&lt;/thead&gt; &lt;tbody&gt;&lt;tr&gt;     &lt;td&gt;1.&lt;/td&gt;     &lt;td&gt;Linux&lt;/td&gt;     &lt;td&gt;56,18%&lt;/td&gt;   &lt;/tr&gt;&lt;tr&gt;     &lt;td&gt;2.&lt;/td&gt;     &lt;td&gt;Windows&lt;/td&gt;     &lt;td&gt;33,71%&lt;/td&gt;   &lt;/tr&gt;&lt;tr&gt;     &lt;td&gt;3.&lt;/td&gt;     &lt;td&gt;Macintosh&lt;/td&gt;     &lt;td&gt;8,24%&lt;/td&gt;   &lt;/tr&gt;&lt;tr&gt;     &lt;td&gt;4.&lt;/td&gt;     &lt;td&gt;FreeBSD&lt;/td&gt;     &lt;td&gt;1,12%&lt;/td&gt;   &lt;/tr&gt;&lt;tr&gt;     &lt;td&gt;5.&lt;/td&gt;     &lt;td&gt;SunOS&lt;/td&gt;     &lt;td&gt;0,37%&lt;/td&gt;   &lt;/tr&gt;&lt;tr&gt;     &lt;td&gt;6.&lt;/td&gt;     &lt;td&gt;SymbianOS&lt;/td&gt;     &lt;td&gt;0,37%&lt;/td&gt;   &lt;/tr&gt;&lt;/tbody&gt; &lt;/table&gt;&lt;br /&gt;Navegadores &lt;br /&gt;&lt;br /&gt;&lt;table style="width: 20em;"&gt;&lt;thead&gt;&lt;tr&gt;     &lt;td&gt;Pos&lt;/td&gt;     &lt;td&gt;Navegador&lt;/td&gt;     &lt;td&gt;Rata&lt;/td&gt;   &lt;/tr&gt;&lt;/thead&gt; &lt;tbody&gt;&lt;tr&gt;     &lt;td&gt;1.&lt;/td&gt;     &lt;td&gt;Firefox&lt;/td&gt;     &lt;td&gt;44,94%&lt;/td&gt;   &lt;/tr&gt;&lt;tr&gt;     &lt;td&gt;2.&lt;/td&gt;     &lt;td&gt;Mozilla&lt;/td&gt;     &lt;td&gt;30,71%&lt;/td&gt;   &lt;/tr&gt;&lt;tr&gt;     &lt;td&gt;3.&lt;/td&gt;     &lt;td&gt;Chrome&lt;/td&gt;     &lt;td&gt;8,24%&lt;/td&gt;   &lt;/tr&gt;&lt;tr&gt;     &lt;td&gt;4.&lt;/td&gt;     &lt;td&gt;Internet Explorer&lt;/td&gt;     &lt;td&gt;7,12%&lt;/td&gt;   &lt;/tr&gt;&lt;tr&gt;     &lt;td&gt;5.&lt;/td&gt;     &lt;td&gt;Safari&lt;/td&gt;     &lt;td&gt;5,99%&lt;/td&gt;   &lt;/tr&gt;&lt;tr&gt;     &lt;td&gt;6.&lt;/td&gt;     &lt;td&gt;Opera&lt;/td&gt;     &lt;td&gt;3,00%&lt;/td&gt;   &lt;/tr&gt;&lt;/tbody&gt; &lt;/table&gt;&lt;br /&gt;Ojalá que mas gente aprenda Perl ;-)&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5238463735728501931-3268827210871305081?l=perliscopio.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://perliscopio.blogspot.com/feeds/3268827210871305081/comments/default' title='Enviar comentarios'/><link rel='replies' type='text/html' href='http://perliscopio.blogspot.com/2009/09/los-perleros-no-usan-ie.html#comment-form' title='0 comentarios'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5238463735728501931/posts/default/3268827210871305081'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5238463735728501931/posts/default/3268827210871305081'/><link rel='alternate' type='text/html' href='http://perliscopio.blogspot.com/2009/09/los-perleros-no-usan-ie.html' title='Los Perleros no usan IE'/><author><name>Jose Rey</name><uri>http://www.blogger.com/profile/15071755167581242815</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5238463735728501931.post-497357417890569647</id><published>2009-09-05T19:40:00.005-04:30</published><updated>2009-09-06T09:49:04.010-04:30</updated><category scheme='http://www.blogger.com/atom/ns#' term='Comunidad'/><category scheme='http://www.blogger.com/atom/ns#' term='Perl'/><category scheme='http://www.blogger.com/atom/ns#' term='Lenguajes'/><category scheme='http://www.blogger.com/atom/ns#' term='Programación Funcional'/><title type='text'>El renacimiento de Perl</title><content type='html'>[&lt;a href="http://translate.google.com/translate?prev=hp&amp;amp;hl=en&amp;amp;js=y&amp;amp;u=http%3A%2F%2Fperliscopio.blogspot.com%2F2009%2F09%2Fel-renacimiento-de-perl.html&amp;amp;sl=es&amp;amp;tl=en&amp;amp;history_state0="&gt;Google English Translation&lt;/a&gt;]&lt;br /&gt;En el año 2006 estaba coordinando 2 proyectos, uno de ellos era una aplicación web (obviamente en &lt;a href="http://www.catalystframework.org/"&gt;Catalyst&lt;/a&gt;), y parte de mi trabajo es buscar mejores herramientas para facilitar la labor de los programadores, así fue como me topé por primera vez con &lt;a href="http://www.iinteractive.com/moose/"&gt;Moose&lt;/a&gt;, que aunque incipiente, captó mi atención de inmediato, así seguí los enlaces hacia &lt;a href="http://search.cpan.org/dist/Class-MOP/"&gt;Class::MOP&lt;/a&gt;, donde me hablaban del &lt;a href="http://en.wikipedia.org/wiki/Metaobject"&gt;Meta Object Protocol&lt;/a&gt;, y por terminé aprendiendo algo de &lt;a href="http://es.wikipedia.org/wiki/Lisp"&gt;Common Lisp&lt;/a&gt; y particularmente &lt;a href="http://es.wikipedia.org/wiki/CLOS"&gt;CLOS&lt;/a&gt;.&lt;br /&gt;Más o menos al mismo tiempo estaba coordinando el desarrollo de un sistema distribuido para Linux (en C++ por requerimiento del cliente), y también estaba en la búsqueda de alguna herramienta que aliviara el dolor de que nos causaba ese desarrollo, conocí &lt;a href="http://radarlibre.blogspot.com/2007/11/un-lenguaje-de-ciencia-ficcin.html"&gt;Erlang&lt;/a&gt; y redescubrí la programación funcional, que me llevaron finalmente a OCaml, Haskell y Scheme.&lt;br /&gt;Así que el 2006 y 2007 fueron años de diversión, aprendiendo nuevos lenguajes, mecanismos y paradigmas de programación, lo interesante es que a pesar de adquirir pericias en herramientas tan bien hechas y con una potencia impresionante como las mencionadas, todavía hoy, quien me ayuda a poner la comida en la mesa es principalemente Perl.&lt;br /&gt;Algunos profetas del desastre predicen periódicamente la muerte de Perl, sin embargo, todavía se consigue más trabajo en Perl que en otros lenguajes similares, como se aprecia haciendo una &lt;a href="http://www.indeed.com/jobtrends?q=perl%2Cpython%2Cphp%2Cruby&amp;amp;l="&gt;búsqueda en indeed&lt;/a&gt;. Cuando les vengan con el cuento de que Perl está muerto no caigan por inocentes, porque en realidad está vivo y tomando impulso nuevamente. Algunos argumentarán que el crecimiento de los otros es más rápido, pero Perl tiene una base de muy grande de código en producción, y le es más difícil crecer, pero ya cruzo la línea de la inmortalidad.&lt;br /&gt;Perl6, al que perdí de vista en el 2005, siguió su avance y logró renovar el interés en Perl5, cuya evolución reciente esta muy influenciada por el desarrollo de su sucesor. Por ejemplo: el sistema de OOP de Perl6 se implementó en Perl5 (Moose), instrucciones como el &lt;a href="http://perldoc.perl.org/perlsyn.html#Switch-statements"&gt;given/when&lt;/a&gt;, que aparece en Perl 5.10 y reemplazan al módulo &lt;a href="http://perldoc.perl.org/Switch.html"&gt;Switch&lt;/a&gt;, vienen directamente de la sintaxis de Perl6.&lt;br /&gt;Perl5 también evoluciona en la dirección del paradigma funcional, hace unos días leí la presentación &lt;a href="http://yapceurope2009.org/ye2009/talk/1883"&gt;Functional Pe(a)rls&lt;/a&gt;, dictada en el &lt;a href="http://yapceurope2009.org/"&gt;YAPC::EU::2009&lt;/a&gt;, así descubrí &lt;a href="http://github.com/osfameron/Foose/tree/master"&gt;Foose&lt;/a&gt;: un proyecto que intenta introducir en Perl las características importantes de los lenguajes funcionales (principalmente Haskell), tales como listas flojas, mónadas y currificación, siempre cuidando la compatibilidad y la interacción con Moose.&lt;br /&gt;Todos estos cambios interactúan y se retroalimentan del &lt;a href="http://cpan.org/"&gt;CPAN&lt;/a&gt;, la cantidad de módulos que utilizan Moose ha ido en aumento y ya &lt;a href="http://cpants.perl.org/dist/used_by/Moose"&gt;Moose es una dependencia común para muchos módulos&lt;/a&gt;, incluyendo Catalyst. &lt;br /&gt;Foose a su vez usa nuevos módulos como &lt;a href="http://search.cpan.org/dist/Devel-Declare/lib/Devel/Declare.pm"&gt;Devel::Declare&lt;/a&gt;, un módulo casi mágico que permite introducir nuevos elementos sintácticos en Perl, llevando la meta-programación en este lenguaje a un nuevo nivel de abstracción.&lt;br /&gt;El excelente libro &lt;a href="http://oreilly.com/catalog/9780596001735/"&gt;Perl Best Practices&lt;/a&gt;, ha sido un factor determinante en un cambio cultural de la comunidad, que ahora se enfatiza el buen estilo, la claridad del código y las interfaces, mientras se intenta dejar atrás en la historia a los JAPHs y la mala fama de lenguaje ilegible, &lt;a href="http://perliscopio.blogspot.com/2009/08/perl-arcaico.html"&gt;por demás injustificada&lt;/a&gt;.&lt;br /&gt;Haciendo alarde de su capacidad, la comunidad de Perl va mucho más allá que la de otros lenguajes, y elabora herramientas que permiten evaluar la calidad del código que se genera, así nacieron módulos como &lt;a href="http://search.cpan.org/%7Eelliotjs/Perl-Critic-1.104/lib/Perl/Critic.pm"&gt;Perl::Critic&lt;/a&gt; y &lt;a href="http://search.cpan.org/%7Echromatic/Test-Kwalitee-1.01/lib/Test/Kwalitee.pm"&gt;Test::Kwalitee&lt;/a&gt;, que evalúan las prácticas de programación y las critican permitiendo al programador elevar la calidad de su código, y como&amp;nbsp; consecuencia la mejora global de las librerías del &lt;a href="http://cpan.org/"&gt;CPAN&lt;/a&gt;.&lt;br /&gt;En resumen, desde hace algún tiempo hay un proceso de renovación tecnológica y cultural que por definición son el Renacimiento de Perl.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5238463735728501931-497357417890569647?l=perliscopio.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://perliscopio.blogspot.com/feeds/497357417890569647/comments/default' title='Enviar comentarios'/><link rel='replies' type='text/html' href='http://perliscopio.blogspot.com/2009/09/el-renacimiento-de-perl.html#comment-form' title='3 comentarios'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5238463735728501931/posts/default/497357417890569647'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5238463735728501931/posts/default/497357417890569647'/><link rel='alternate' type='text/html' href='http://perliscopio.blogspot.com/2009/09/el-renacimiento-de-perl.html' title='El renacimiento de Perl'/><author><name>Jose Rey</name><uri>http://www.blogger.com/profile/15071755167581242815</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>3</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5238463735728501931.post-7935976618693974128</id><published>2009-08-31T21:29:00.002-04:30</published><updated>2009-09-05T20:11:06.456-04:30</updated><category scheme='http://www.blogger.com/atom/ns#' term='Tutorial'/><category scheme='http://www.blogger.com/atom/ns#' term='Perl'/><category scheme='http://www.blogger.com/atom/ns#' term='Programación'/><title type='text'>La magia de Perl</title><content type='html'>[&lt;a haref="http://translate.google.com/translate?prev=hp&amp;amp;hl=en&amp;amp;js=y&amp;amp;u=http%3A%2F%2Fperliscopio.blogspot.com%2F2009%2F08%2Fla-magia-de-perl.html&amp;amp;sl=es&amp;amp;tl=en&amp;amp;history_state0=" href=""&gt;Google english translation&lt;/a&gt;]&lt;br /&gt;Una de las características que hacen de perl una navaja suiza (por cierto afilada) son las construcciones mágicas del lenguaje, que permiten escribir micro programas rápida y fácilmente, y es una de las razones por las cuales el lenguaje tiene fama de incomprensible.&lt;br /&gt;Aunque el uso de estas construcciones están contraindicadas en la programación de sistemas, son de gran utilidad en el día a día de los administradores de sistemas y programadores, por ello voy a explicar las más comunes, para que puedas apreciar su potencia y entender los scripts que se crucen en tu camino.&lt;br /&gt;&lt;h2&gt;El operador de lectura&lt;/h2&gt;En Perl se puede leer &lt;i&gt;una línea&lt;/i&gt; de la entrada estándar de la siguiente manera:&lt;br /&gt;&lt;pre&gt;&lt;code&gt;&lt;br /&gt;my $linea = readline(STDIN);&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;Sin embargo también existe el operador de lectura &lt;code&gt;&amp;lt;ARCHIVO&amp;gt;&lt;/code&gt; que permite leer &lt;i&gt;una línea&lt;/i&gt; así:&lt;br /&gt;&lt;pre&gt;&lt;code&gt;&lt;br /&gt;my $línea = &amp;lt;STDIN&amp;gt;;&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;adicionalmente si el archivo es STDIN se puede omitir el nombre en el operador, quedando simplemente:&lt;br /&gt;&lt;pre&gt;&lt;code&gt;&lt;br /&gt;my $linea = &amp;lt;&amp;gt;;&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;Cuando enfaticé "&lt;i&gt;una línea&lt;/i&gt;" en los párrafos anteriores lo hice porque en Perl no se leen líneas, en realidad se leen registros, claro que por defecto los registros están definidos como texto terminado por &lt;i&gt;fines de línea&lt;/i&gt;, que a su vez tienen un significado diferente en cada plataforma, por ejemplo en Unix el fin de línea es "\n", mientras que en Windows es "\r\n".&lt;br /&gt;&lt;h2&gt;El acumulador o Variable Implícita ($_)&lt;/h2&gt;Es una variable global que se utiliza implícitamente, sobre todo en las operaciones mágicas, su nombre viene de la similitud con el acumulador en &lt;a href="http://es.wikipedia.org/wiki/Lenguaje_ensamblador"&gt;Ensamblador&lt;/a&gt; que se utiliza implícitamente, aunque es mejor llamarla "Variable Implícita", el nombre de esta variable en Perl es: "&lt;code&gt;$_&lt;/code&gt;".&lt;br /&gt;Uno de los usos más comunes de la variable implícita es en la prueba de expresiones regulares, normalmente cuando quieres saber si el contenido de una variable concuerda con una expresión regular haces:&lt;br /&gt;&lt;pre&gt;&lt;code&gt;&lt;br /&gt;if ( $texto =~ m/lo que se busca/ ) { ...&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;Pues bien, si el texto se encuentra en &lt;code&gt;$_&lt;/code&gt; entonces se puede hacer:&lt;br /&gt;&lt;pre&gt;&lt;code&gt;&lt;br /&gt;if ( m/lo que se busca/ ) { ...&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;Además &lt;code&gt;$_&lt;/code&gt; se utiliza en algunas funciones de la librería como &lt;code&gt;split&lt;code&gt; y &lt;code&gt;print&lt;code&gt;, por ejemplo:&lt;br /&gt;&lt;/code&gt;&lt;/code&gt;&lt;/code&gt;&lt;/code&gt;&lt;br /&gt;&lt;pre&gt;&lt;code&gt;&lt;br /&gt;@campos = split( /,/, $texto );&lt;br /&gt;@campos = split /,/;&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;La primera línea pica el contenido de la variable $texto (por las comas) mientras la segunda hace lo mismo utilizando implícitamente el contenido de &lt;code&gt;$_&lt;/code&gt;. Algo similar sucede con &lt;code&gt;print&lt;/code&gt;. Por cierto, ¿se notó que la segunda llamada no tiene paréntesis?, eso es producto de que en Perl esos paréntesis son opcionales (pero dejaré eso para otro artículo).&lt;br /&gt;&lt;h2&gt;El ciclo mágico&lt;/h2&gt;Cuando se combina &lt;code&gt;$_&lt;/code&gt; el operador de lectura &lt;code&gt;&amp;lt;&amp;gt;&lt;/code&gt; y un ciclo &lt;code&gt;while&lt;/code&gt; tenemos el ciclo mágico de Perl:&lt;br /&gt;&lt;pre&gt;&lt;code&gt;&lt;br /&gt;while ( &amp;lt;&amp;gt; ) {&lt;br /&gt;    print;  # se imprime $_ implícitamente &lt;br /&gt;}&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;Este ciclo lee de la entrada estándar mientras haya &lt;i&gt;líneas&lt;/i&gt; que leer, y el resultado de cada lectura queda en &lt;code&gt;$_&lt;/code&gt;, en efecto el programa anterior se parece mucho a &lt;code&gt;cat(1)&lt;/code&gt; de Unix, supongamos que tenemos este programa instalado con el nombre &lt;code&gt;plcat&lt;/code&gt;, entonces:&lt;br /&gt;&lt;pre&gt;&lt;code&gt;&lt;br /&gt;$ plcat &amp;lt; archivo.txt&lt;br /&gt;$ plcat &amp;lt; fuente.txt &amp;gt; destino.txt&lt;br /&gt;$ ls -R / | plcat&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;Hacen exactamente lo mismo que &lt;code&gt;cat(1)&lt;/code&gt;, pero además hace más magia, así que:&lt;br /&gt;&lt;pre&gt;&lt;code&gt;&lt;br /&gt;$ plcat archivo.txt&lt;br /&gt;$ plcat archivo.txt otro.txt&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;Incluso el argumento "-" de cat funciona igual!:&lt;br /&gt;&lt;pre&gt;&lt;code&gt;&lt;br /&gt;$ plcat archivo.txt - otro.txt&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;h2&gt;El ciclo mágico implícito&lt;/h2&gt;El ciclo mágico puede omitirse si perl se invoca con alguna de las opciones &lt;code&gt;-p&lt;/code&gt; ó &lt;code&gt;-n&lt;/code&gt;, la primera envuelve todo el código de Perl en el ciclo que antes vimos, con el &lt;code&gt;print&lt;/code&gt; al final, la segunda hace lo mismo pero omite el &lt;code&gt;print&lt;/code&gt;. Así que el programa anterior se puede escribir en una sola línea de perl:&lt;br /&gt;&lt;code&gt;&lt;/code&gt;&lt;br /&gt;&lt;pre&gt;$ perl -ne 'print' archivo.txt&lt;br /&gt;&lt;/pre&gt;Aunque como -p también incluye el &lt;code&gt;print&lt;/code&gt; podemos hacer:&lt;br /&gt;&lt;pre&gt;&lt;code&gt;$ perl -pe '' archivo.txt&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;h2&gt;Un ejemplo práctico&lt;/h2&gt;Una forma de escribir &lt;code&gt;grep&lt;/code&gt; en Perl sería:&lt;br /&gt;&lt;code&gt;&lt;/code&gt;&lt;br /&gt;&lt;pre&gt;#!/usr/bin/env perl&lt;br /&gt;my $patron = shift(@ARGV);&lt;br /&gt;while (&amp;lt;&amp;gt;) {&lt;br /&gt;    print "$ARGV:$.: $_" if m/$patron/; &lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;La variable &lt;code&gt;$ARGV&lt;/code&gt; contiene el nombre del archivo actualmente abierto por el ciclo mágico, y la variable &lt;code&gt;$.&lt;/code&gt; contiene el número de la última línea leída. Todo esto se puede hacer directamente desde la línea de comandos:&lt;br /&gt;&lt;code&gt;&lt;/code&gt;&lt;br /&gt;&lt;pre&gt;$ perl -ne 'print "$ARGV:$.: $_" if m/lo que busco/'&lt;br /&gt;&lt;/pre&gt;Y después de saber como funcionan los operadores lógicos en Perl, puedo hacerlo así también:&lt;br /&gt;&lt;pre&gt;&lt;code&gt;&lt;br /&gt;$ perl -ne '/lo que busco/ &amp;amp;&amp;amp; print "$ARGV:$.: $_"'&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;h2&gt;El separador de registros&lt;/h2&gt;Ya mencione que el concepto de línea en Perl en realidad significa registro, y que los registros se definen por defecto para coincidir con el fin de línea del sistema operativo. La  variable global que configura como se interpretan los registros en Perl es &lt;code&gt;$/&lt;/code&gt;, así que si se  necesita procesar un archivo separado por una cadena particular solamente se asigna esa cadena a   &lt;code&gt;$/&lt;/code&gt;.&lt;br /&gt;Esta variable tiene valores especiales para lograr diversos efectos, el primer valor especial es indefinido, cuando &lt;code&gt;$/ = undef&lt;/code&gt;, el registro es todo el archivo, así que:&lt;br /&gt;&lt;code&gt;&lt;/code&gt;&lt;br /&gt;&lt;pre&gt;$todo = readline(STDIN);&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;Lee todo el archivo en la variable, se imaginarán que si el archivo es un DVD probablemente te quedarás sin memoria antes de que el programa termine.&lt;br /&gt;Otro valor interesante es la cadena vacía, que permite leer registros de varias líneas delimitados por líneas en blanco, el siguiente programa lee un &lt;a href="http://ftp.debian.org/debian/dists/lenny/main/binary-i386/Packages.bz2"&gt;archivo de paquetes de Debian&lt;/a&gt; paquete por paquete imprimiendo el nombre de cada paquete:&lt;br /&gt;&lt;code&gt;&lt;/code&gt;&lt;br /&gt;&lt;pre&gt;#!/usr/bin/env perl&lt;br /&gt;$/ = '';&lt;br /&gt;while (&amp;lt;&amp;gt;) {&lt;br /&gt;    /^Package:\s+(.*)/m or die "Error de sintaxis";&lt;br /&gt;    print "$1\n";&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;Y por supuesto su correspondiente programa de una línea:&lt;br /&gt;&lt;code&gt;&lt;/code&gt;&lt;br /&gt;&lt;pre&gt;$ perl -ne '/^Package:\s+(.*)/m &amp;amp;&amp;amp; print "$1\n"'&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;h2&gt;Recomendaciones finales&lt;/h2&gt;El propósito de este artículo es dar a conocer técnicas importantes que ayudan a resolver problemas puntuales, sin embargo, casi todo lo aquí expuesto debe evitarse para programas que sean de más de una docena de líneas o cuando se pretenda instalar un programa como herramienta en una organización.&lt;br /&gt;Para programas grandes ó duraderos:&lt;br /&gt;&lt;ul&gt;&lt;li&gt;Evita &lt;code&gt;$_&lt;/code&gt; excepto cuando no haya más remedio, o en pequeños trozos de código donde esté topicalizada y aún así es mejor usar una variable local (declarada con &lt;code&gt;my&lt;/code&gt;), si no sabes que es eso de la topicalización no uses &lt;code&gt;$_&lt;/code&gt;.&lt;/li&gt;&lt;li&gt;Usa preferiblemente &lt;code&gt;readline()&lt;/code&gt; en vez del operador de lectura, porque hay mas chance de que un novato entienda el programa.&lt;/li&gt;&lt;li&gt;No uses &lt;code&gt;$/&lt;/code&gt; pues cambia el comportamiento de todos los archivos abiertos en perl, esto es común para algunas otras variables que configuran el ambiente operativo en perl y que puedes consultar con el comando: &lt;code&gt;perldoc&amp;nbsp;perlvar&lt;/code&gt;&lt;/li&gt;&lt;/ul&gt;Suficiente magia por hoy.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5238463735728501931-7935976618693974128?l=perliscopio.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://perliscopio.blogspot.com/feeds/7935976618693974128/comments/default' title='Enviar comentarios'/><link rel='replies' type='text/html' href='http://perliscopio.blogspot.com/2009/08/la-magia-de-perl.html#comment-form' title='0 comentarios'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5238463735728501931/posts/default/7935976618693974128'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5238463735728501931/posts/default/7935976618693974128'/><link rel='alternate' type='text/html' href='http://perliscopio.blogspot.com/2009/08/la-magia-de-perl.html' title='La magia de Perl'/><author><name>Jose Rey</name><uri>http://www.blogger.com/profile/15071755167581242815</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5238463735728501931.post-8925531969948477370</id><published>2009-08-24T11:56:00.005-04:30</published><updated>2009-09-18T09:39:51.542-04:30</updated><category scheme='http://www.blogger.com/atom/ns#' term='Comunidad'/><category scheme='http://www.blogger.com/atom/ns#' term='Perl'/><category scheme='http://www.blogger.com/atom/ns#' term='Mitos'/><category scheme='http://www.blogger.com/atom/ns#' term='Estilo'/><title type='text'>Perl arcaico</title><content type='html'>[&lt;a href="http://perliscope.blogspot.com/2009/08/archaic-perl.html"&gt;English translation&lt;/a&gt;]&lt;br /&gt;Hace un par de dias me tocó atender un proveedor que vino a ofrecer sus servicios para el desarrollo de una aplicación web.&lt;br /&gt;Como alguno de los participantes de la organización tuvo que manejar un imprevisto aproveché para iniciar un pequeña investigación durante la charla informal: "¿Que herramientas de desarrollo utilizan en su empresa?".&lt;br /&gt;En un mundo ideal la respuesta hubiera sido: "Perl", pero me informaron que ellos trabajan principalmente en Python, aunque pueden trabajar en otros ambientes, incluyendo Perl.&lt;br /&gt;Después de informarles que en la organización preferimos Perl para el desarrollo de nuestras aplicaciones, y después de un micro debate religioso, uno de ellos (Juan) concluyó:&lt;br /&gt;&lt;blockquote&gt;En definitiva cualquier cosa que se puede hacer en un lenguaje se puede hacer en el otro, solo que en Perl la programación es más arcaica&lt;br /&gt;&lt;/blockquote&gt;en aquel momento casi me altero, pero en vista de que llegó el que faltaba y que lo importante era la reunión, me quedé tranquilo.&lt;br /&gt;Ahora en retrospectiva me pregunto: ¿a qué se refería con eso de que Perl es arcaico?, tal vez, Juan se refería a Perl 1 (1987), que era una especie de Shell Script con grep, sed y awk incluido, incluso pudiera pensar que dijera eso hasta de Perl 4 (1991, un poco después de Python 1.0), sin embargo la era actual de Perl es 5 (1994) y en vista de la edad del personaje, creo que en realidad Juan no encontró una palabra que describiera todos los &lt;i&gt;&lt;b&gt;míticos&lt;/b&gt;&lt;/i&gt; defectos de Perl y terminó usando la palabra incorrecta.&lt;br /&gt;Si Perl fuera arcaico, probablemente la programación orientada a objetos y la programación funcional también lo sean, sin embargo son las dos tecnologías con más impulso en la actualidad, y dado que incluso &lt;a href="http://www.perl.com/pub/a/2007/12/06/soto-11.html"&gt;el sistema de orientación a objetos de Perl fue copiado de Python&lt;/a&gt;, asumiré que quiso decir alguna de las siguientes:&lt;br /&gt;&lt;ol&gt;&lt;li&gt;Perl es feo&lt;/li&gt;&lt;li&gt;Perl es desordenado&lt;/li&gt;&lt;li&gt;Perl es ilegible&lt;/li&gt;&lt;li&gt;Perl es incomprensible&lt;br /&gt;&lt;/li&gt;&lt;/ol&gt;Voy a responder brevemente a estos prejuicios que se han difundido ampliamente por Internet y para los cuales no hay un sustento real, y mucho menos después del renacimiento de Perl (del que hablaré en otro artículo).&lt;br /&gt;&lt;h2&gt;Perl es feo&lt;/h2&gt;Como eso es cuestión de gustos, lo que es feo para algunos puede ser muy atractivo para otros. Pero &lt;i&gt;suponiendo&lt;/i&gt; que Perl es uno de los lenguajes más feos, tiene características que lo hacen un lenguaje único para resolver una gran cantidad de problemas con facilidad.&lt;br /&gt;Una de las características que hacen la sintaxis de Perl recargada (no necesariamente fea) son los sellos (sigils) que indican el tipo de cada variable, sin embargo esto facilita la extensibilidad del lenguaje y permite la interpolación en las cadenas, y cuando me refiero a que Perl es extensible quiero decir que se puede intervenir en el proceso de compilación para cambiar la sintaxis original, una característica de muy alto nivel que comparte con muy pocos lenguajes, y que es el fundamento de los &lt;a href="http://www.agile-spain.com/?q=/lenguajededominioespecifico"&gt;lenguajes de dominio específico&lt;/a&gt; (o &lt;a href="http://en.wikipedia.org/wiki/Domain-specific_programming_language"&gt;DSL&lt;/a&gt;s por sus siglas en inglés) que son muy útiles y populares. Perl ofrece al menos tres mecanismos diferentes para lograr este objetivo.&lt;br /&gt;Otra característica es la práctica integración de las expresiones regulares en el lenguaje, logrando el uso extensivo de las mismas, lamentablemente dichas expresiones son feas sin importar el lenguaje. Tomemos como ejemplo el reconocimiento de una instrucción específica de LaTeX:&lt;br /&gt;&lt;code&gt;&lt;br /&gt;\begin{document}&lt;br /&gt;&lt;/code&gt;&lt;br /&gt;En Perl se vería algo como:&lt;br /&gt;&lt;code&gt;&lt;br /&gt;if ( $latex =~ m/\\begin\{[a-z]+\}/ ) ...&lt;br /&gt;&lt;/code&gt;&lt;br /&gt;En Python:&lt;br /&gt;&lt;code&gt;&lt;br /&gt;patron = re.compile(r'\\begin\{[a-z]+\}')&lt;br /&gt;if &lt;/code&gt;&lt;code&gt;patron.match(latex)&lt;/code&gt;&lt;code&gt;:&lt;br /&gt;...&lt;br /&gt;&lt;/code&gt;&lt;br /&gt;En realidad ninguno de los dos es bonito, pero realmente en Perl es más sucinto y hasta más fácil de entender, y eso que no muestro lo tedioso que es usarlas en Java.&lt;br /&gt;Finalmente está el bendito argumento sobre el estilo y todo aquella tontería de que el compilador obliga a indentar correctamente. Lo digo porque aún cuando es cierto que uno termina acostumbrándose, también es cierto que a veces es un fastidio y estorba, y en esos casos no hay remedio. Mas adelante hay un ejemplo de Python que no es fácil de formatear por lo inflexible de la sintaxis.&lt;br /&gt;Cuando se requiere un estilo de código en particular, se usan herramientas de formateo, por ejemplo para C yo uso &lt;code&gt;indent&lt;/code&gt;, y para Perl uso &lt;code&gt;perltidy&lt;/code&gt;, últimamente el código que escribo suele estar en el siguiente estilo:&lt;br /&gt;&lt;code&gt;&lt;br /&gt;perltidy -l=99 -sbl&lt;br /&gt;&lt;/code&gt;&lt;br /&gt;No importa como me entreguen el código o como lo transcriba yo mismo, porque lo puedo poner en mi estilo estándar con un solo comando, incluso antes de salvarlo (porque además uso vim). &lt;br /&gt;&lt;h2&gt;Perl es desordenado&lt;/h2&gt;Los lenguajes no son desordenados, la gente lo es.&lt;br /&gt;Sin embargo hay lenguajes que tienen más mecanismos que otros para organizar un proyecto, en particular Perl ofrece varias formas de organizar el código que se adaptan a muchas necesidades, que van desde la programación en una sola línea (de comandos), hasta la construcción de aplicaciones grandes y complejas.&lt;br /&gt;El lenguaje permite la creación de módulos procedimentales con sus propios espacios de nombres, que incluso se pueden organizar en multiples archivos para ser cargados "on demand", bien enterprise, ¿cierto?.&lt;br /&gt;Perl tiene un sistema básico de orientación a objetos que permite implementar OOP de muchas maneras diferentes, porque mientras muchos lenguajes solo hay una forma fija de manejar objetos, en Perl: "hay más de una forma de hacerlo".&lt;br /&gt;Lo que &lt;b&gt;no&lt;/b&gt; hace perl es obligar al programador a seguir una estructura determinada, sin importar si eso se adapta a las necesidades de un programa específico, porque si hiciera eso se parecería a Java. &lt;br /&gt;&lt;h2&gt;Perl es ilegible&lt;/h2&gt;Esto es solo una combinación particular de los dos mitos que le preceden, aunque también se usa el argumento de que no se puede leer el código que se escribío hace 15 min. y eso bajo ciertas circunstancias es bueno, porque permite escribir programas rápidamente aunque sean sucios, después de todo nadie quiere ponerse a diseñar y documentar siguiendo los principios de ingeniería de software para comprender el último programa que escribí hace unas horas, únicamente porque necesitaba una pista sobre la frecuencia de aparición de los caracteres en una docena de archivos:&lt;br /&gt;&lt;code&gt;&lt;br /&gt;perl -MYAML -ne '$c{$_}++for split//;END{print Dump\%c}' datos.txt&lt;br /&gt;&lt;/code&gt;&lt;br /&gt;Es más fácil escribirlo nuevamente que intentar comprenderlo, claro que el programa es una tontería en Perl porque tiene ciertas construcciones mágicas, pero no intenten algo así con otro lenguaje, porque su mejor escenario es lograr que funciona, pero garantizo que va a ser mucho más largo y difícil.&lt;br /&gt;Sin embargo Perl también permite escribir el código mas bonito si eso fuera lo necesario:&lt;br /&gt;&lt;pre&gt;&lt;code&gt;&lt;br /&gt;use YAML;&lt;br /&gt;use IO::File;&lt;br /&gt;use strict;&lt;br /&gt;&lt;br /&gt;my %cuentas;&lt;br /&gt;my $fd = new IO::File $ARGV[0], "r";&lt;br /&gt;while ( my $line = readline($fd) ) {&lt;br /&gt;    for my $letra ( split( //, $line ) ) {&lt;br /&gt;        $cuentas{$letra}++;&lt;br /&gt;    }&lt;br /&gt;}&lt;br /&gt;print YAML::Dump( \%cuentas )&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;Estoy seguro de que no es muy difícil para un programador de Python o Ruby comprender lo que hace ese código ¿o sí?, luego la cuestión no es que el lenguaje sea ilegible, sino la motivación para escribir el programa y en todo caso la inteligencia del programador para escribir código legible o fácilmente mantenible aún por compañeros poco experimentados.&lt;br /&gt;Finalmente la menor de mis preocupaciones fue el formato del código, pues la mayoría del trabajo lo hace mi editor automáticamente, pero por si acaso también lo pase por perltidy para que vean lo bien formateado que queda.&lt;br /&gt;&lt;h2&gt;Perl es incomprensible&lt;/h2&gt;¿Para quién?, por ejemplo, el japonés es incomprensible para mi, pero dudo que lo sea para la mayoría de la gente que vive en Tokio, de igual manera Perl es incomprensible para alguien que no este entrenado para comprenderlo. En la sección anterior di un ejemplo de que se puede trabajar en Perl escribiendo el código de manera tan clara como en Python o en Java.&lt;br /&gt;Ciertamente hay mucho código Perl que es &lt;a href="http://perl.plover.com/obfuscated/"&gt;prácticamente incomprensible&lt;/a&gt; excepto para los gurúes del lenguaje, pero eso no significa que los programas deban escribirse de esa manera.&lt;br /&gt;Lo que si es cierto es que la forma sucinta que permite ofuscar el código hace de perl, no solo un interpretador sino una herramienta de uso común en la línea de comandos y al mismo tiempo permite la expresión del &lt;a href="http://www.ibm.com/developerworks/linux/library/l-japh.html"&gt;ingenio y maestría&lt;/a&gt; en el dominio del lenguaje. Hay muy pocos lenguajes que permitan hacer los &lt;a href="http://www.cpan.org/misc/japh"&gt;JAPHs&lt;/a&gt; como Perl.&lt;br /&gt;La falacia aparece cuando se dicen cosas como: "Perl es maligno porque permite esas cosas", "En Python es imposible hacer programas incomprensibles", ¿ah si?, a ver quien entiende este programita en Python:&lt;br /&gt;&lt;pre&gt;&lt;code&gt;&lt;br /&gt;for n in range(12):&lt;br /&gt;    exec("abcdefghijkl"[n]+"=lambda x=0,y=0: "+filter(&lt;br /&gt;        lambda x:x not in "\n$\r","""(x*y#x/x!range(x,&lt;br /&gt;y#x+y!b(1,1#d(e~,e~#d(f~,f~#c(e~,e~+d(g~,d(g~,g~))#"%4&lt;br /&gt;d" % a(x,y#map(lambda y:i(x,y),h~#" ".join(j(x)#"\\n".&lt;br /&gt;join(map(k,h~))""".replace("~","()").replace("#",")!")&lt;br /&gt;        ).split("!")[n])&lt;br /&gt;print l()&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;Y puedo buscar cosas mucho más feas en Java, lo que significa que se pueden escribir programas incomprensibles en cualquier lenguaje, y un novato probablemente lo pueda hacer simplemente aprovechando su ignorancia. Por ello la importancia del personal calificado sin importar cual sea el lenguaje.&lt;br /&gt;Sin embargo no se aprovechará todo el potencial de los programadores a menos que el lenguaje provea mecanismos de abstracción del más alto nivel, y es en este caso que lenguajes como Java y PHP son bastante malos mientras Perl supera a Python y a Ruby con holgura, descalificando completamente cualquier posibilidad de catalogar a Perl como un lenguaje arcaico.&lt;br /&gt;Perl puede ser tan corporativo como cualquier otro lenguaje, y dominar este lenguaje en una organización, supone una inversión donde el código se puede utilizar y reutilizar de muchas maneras: desde los administradores de sistemas hasta los desarrolladores, pasando por los administradores de base de datos, etc.; en soluciones que van desde una simple operación de línea de comandos hasta la programación de una gran aplicación corporativa.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5238463735728501931-8925531969948477370?l=perliscopio.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://perliscopio.blogspot.com/feeds/8925531969948477370/comments/default' title='Enviar comentarios'/><link rel='replies' type='text/html' href='http://perliscopio.blogspot.com/2009/08/perl-arcaico.html#comment-form' title='3 comentarios'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5238463735728501931/posts/default/8925531969948477370'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5238463735728501931/posts/default/8925531969948477370'/><link rel='alternate' type='text/html' href='http://perliscopio.blogspot.com/2009/08/perl-arcaico.html' title='Perl arcaico'/><author><name>Jose Rey</name><uri>http://www.blogger.com/profile/15071755167581242815</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>3</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5238463735728501931.post-3231355371542021930</id><published>2009-08-23T18:03:00.001-04:30</published><updated>2009-09-05T20:11:40.639-04:30</updated><category scheme='http://www.blogger.com/atom/ns#' term='Perl'/><category scheme='http://www.blogger.com/atom/ns#' term='Noticias'/><title type='text'>Salio perl 5.10.1!</title><content type='html'>A partir de hoy está disponible en el CPAN la &lt;a href="http://search.cpan.org/%7Edapm/perl-5.10.1/"&gt;nueva versión de perl&lt;/a&gt; (5.10.1).&lt;br /&gt;Esta versión acomoda varios bugs que se escaparon en la versión 5.10 e introduce algunas incompatibilidades (muy sutiles, pero incompatibilidades al fin) con 5.10 para mejorar la ortogonalidad del lenguaje, así que asegúrense de leer &lt;a href="http://search.cpan.org/%7Edapm/perl-5.10.1/pod/perl5101delta.pod"&gt;perl5101delta&lt;/a&gt; y especialmente la &lt;a href="http://search.cpan.org/%7Edapm/perl-5.10.1/pod/perl5101delta.pod#Incompatible_Changes"&gt;sección de incompatibilidades&lt;/a&gt;.&lt;div class="blo
