Nota Lane: Hoy me encontré en Twitter muy divertido, a primera vista, un hilo. Y luego miró más de cerca y se dio cuenta de que no solo era divertido, sino también entretenido. Y como sucedió que hoy es viernes, decidí que valía la pena compartir los hallazgos con mis camaradas :)
Guarde el siguiente programa en /tmp/quine.pl
Illegal division by zero at /tmp/quine.pl line 1.
Ejecútalo con el comando
perl /tmp/quine.pl
y ella generará su propio código.
"Quake-tricks" es bastante simple de componer en muchos lenguajes de programación, donde un error de sintaxis en la fuente provoca que un analizador genere un error que coincida con el código fuente del programa.
Publiqué varios de estos trucos en Twitter , incluidos los siguientes:
File "quine.py", line 1 File "quine.py", line 1 ^ IndentationError: unexpected indent
Pero la cebada perlada al comienzo de este artículo es un truco de un tipo completamente diferente: el programa comprende
correctamente .
Y no funciona mucho, hasta que tropieza con el error de división por cero. Este quine es muy sensible a la denominación de archivos; por ejemplo, ejecutar a través de ./quine.pl no funcionará.
¿Entonces este mensaje de error es en realidad todo el programa?
Este programa utiliza mucho del analizador de perlas do-what-I-mean-parser.
El símbolo / depende mucho del contexto de la aplicación y puede considerarse como un símbolo de división o como el comienzo de una expresión regular. E incluso pequeños cambios en el código de este programa conducen a un error al analizar la regularidad y no a la ejecución del código. En este caso, ambos caracteres / aparecen en el contexto del operador.
Otras partes no relacionadas con el diccionario de este programa son
1.
, que se interpreta simplemente como un número y
.
que es un operador de concatenación.
Entonces, ¿qué significan las palabras?
Las palabras en Perl pueden ser nombres de rutinas, métodos, paquetes o clases. ¡O (en modo perezoso) líneas sin separador o tal vez incluso algo más que olvidé!
Perl también utiliza una sintaxis de llamada de método inusual llamada "sintaxis
indirecta de objeto ", que se ve así:
más a menudo puedes ver cómo
print $filehandle "message"; my $instance = new Class(args);
aunque para Perl, es preferible la siguiente sintaxis:
$filehandle->print("message"); my $instance = Class->new(args);
La documentación de
perlobj dice:
Perl utiliza la heurística para analizar este código, en función de los nombres de paquetes que conoce, qué subrutinas existen en el paquete actual, qué palabras ha encontrado antes y analiza otros datos de entrada. ¡No hace falta decir que la heurística puede producir resultados muy inesperados!
¿Cómo analiza este código?
Comenzando en el lado derecho
pl line 1.
analizado como una llamada al método
line->pl(1.)
donde línea es el nombre del paquete (clase) y pl es el método.
En el medio, "at", "tmp" y "quine" se analizan como palabras simples, es decir, cuerdas La expresión se analiza de la siguiente manera:
(("at" / "tmp") / "quine") . line->pl(1.)
A la izquierda hay dos llamadas de método indirecto plegadas,
division->Illegal(zero->by( ... ))
La expresión interna ejecutada primero es:
"at" / "tmp"
Y esto causa instantáneamente la división por cero excepción.