En las aventuras anteriores de la serie de blogs de Quine, exploramos cómo escribir nuestros propios Quines e Intrones. Hoy veremos qué son los QuineRelays y cómo aprovechar los Intrones para crearlos.
Imagínese un círculo de programas, cada uno escrito en un idioma diferente. Cada programa de este círculo tiene un único propósito: imprimir el código fuente del siguiente programa de la secuencia. Luego, el último programa cierra el ciclo imprimiendo el código fuente del primer programa.
Esencialmente, QuineRelays son un conjunto de n programas, en n idiomas diferentes, tales que:
Veamos algunos ejemplos para entender mejor el concepto.
Este QuineRelay de segundo orden presenta un programa JavaScript que imprime un programa Python, que luego imprime el programa JavaScript original. Es un dúo dinámico de autorreplicación.
JavaScript → Python ⥀
JavaScript: ¡Pruébalo online!
console.log((q=_=>`print(${JSON.stringify(`console.log((q=${q []})())`)})`)())
Python: ¡Pruébalo en línea!
print("console.log((q=_=>`print(${JSON.stringify(`console.log((q=${q []})())`)})`)())")
Las cosas se vuelven aún más interesantes con un QuineRelay de tercer orden. Éste comienza con un programa Haskell, que genera un programa Python, que genera un programa Ruby y, finalmente, el programa Ruby regresa al programa Haskell original.
Haskell → Python2 → Ruby ⥀
Haskell: ¡Pruébalo en línea!
q a b c=putStrLn $ b [toEnum 10,'q','('] show b [','] show c [','] show a [')'] main=q "q a b c=putStrLn $ b [toEnum 10,'q','('] show b [','] show c [','] show a [')']" "def q(a,b,c):print b chr(10) 'q(' repr(b) ',' repr(c) ',' repr(a) ')'" "def e(x) return 34.chr x 34.chr end;def q(a,b,c) print b 10.chr 'main=q ' e(b) ' ' e(c) ' ' e(a) ' ' 10.chr end"
Python2: ¡Pruébalo en línea!
def q(a,b,c):print b chr(10) 'q(' repr(b) ',' repr(c) ',' repr(a) ')' q("def q(a,b,c):print b chr(10) 'q(' repr(b) ',' repr(c) ',' repr(a) ')'","def e(x) return 34.chr x 34.chr end;def q(a,b,c) print b 10.chr 'main=q ' e(b) ' ' e(c) ' ' e(a) ' ' 10.chr end","q a b c=putStrLn $ b [toEnum 10,'q','('] show b [','] show c [','] show a [')']")
Ruby: ¡Pruébalo en línea!
def e(x) return 34.chr x 34.chr end;def q(a,b,c) print b 10.chr 'main=q ' e(b) ' ' e(c) ' ' e(a) ' ' 10.chr end q("def e(x) return 34.chr x 34.chr end;def q(a,b,c) print b 10.chr 'main=q ' e(b) ' ' e(c) ' ' e(a) ' ' 10.chr end","q a b c=putStrLn $ b [toEnum 10,'q','('] show b [','] show c [','] show a [')']","def q(a,b,c):print b chr(10) 'q(' repr(b) ',' repr(c) ',' repr(a) ')'")
Aquí hay un QuineRelay de cuarto orden: Ruby → Java → C# → Python ⥀
GitHub
En todas las culturas, existen varios simbolismos compartidos. Uno de ellos es el Ouroboros, que tiene referencias en las mitologías egipcia, griega, romana, hindú, siberiana, nórdica, africana y sudamericana. El Ouroboros es un símbolo antiguo que representa una serpiente o un dragón consumiendo su propia cola, representando el ciclo eterno de creación y destrucción.
En la mitología nórdica, Jörmungandr es una serpiente colosal, el hijo mediano de Loki y la giganta Angrboða. Odín arrojó a Jörmungandr al océano que rodeaba Midgard (el reino de los humanos), donde la serpiente creció tan inmensa que rodeó el mundo y se agarró su propia cola. Como resultado de que rodea a Midgard (la Tierra), se la conoce como la Serpiente Mundial: Ouroboros. Jörmungandr soltando su cola es una de las señales del comienzo de Ragnarök (la batalla final del mundo).
Los relevos de Quine encarnan este simbolismo de manera bastante clara, ya que cada programa en el ciclo da lugar al siguiente, solo para renacer al final, y por eso se les llama programas Ouroboros.
Agarraos en vuestros asientos. Aquí hay un Ouroboros QuineRelay de orden 128. Sí, has leído bien. 128!!!
Ruby → Rust → Scala → ... (otros 120) ... → Python → R → Ratfor → rc → REXX ⥀
GitHub
Como si esto no fuera lo suficientemente impresionante, incluye un huevo de Pascua. ¡El código Ruby original cuando se aleja contiene un dragón Ouroboros!
Comencemos el intrón de Python que escribimos anteriormente e intentemos convertirlo en un QuineRelay de segundo orden.
Python Intron: ¡Pruébelo en línea!
intron = 'wubbalubbadubdub' data = "print('intron =', repr(intron)); print('data =', repr(data)); print(data)" print('intron =', repr(intron)); print('data =', repr(data)); print(data)
Usando la magia de los intrones, ahora podemos colocar fácilmente la parte código de un hermano Quine de un idioma diferente en el intrón. Produciendo un programa de la forma:
Pitón:
intron = "code part of sibling" data = "code part of self" print('intron =', repr(intron)); print('data =', repr(data)); print(data)
Ya que, cada variable es justa, actuando como datos de un Quine diferente. Cambiemos el nombre de datos e intrón a d1 y d2 respectivamente.
Pitón:
d1 = "code part of self" d2 = "code part of sibling" print('d1 =', repr(d1)); print('d2 =', repr(d2)); print(d1)
Ahora, d2 actúa como un intrón, pero el programa anterior aún intentó imprimir parte del código de sí mismo. Para que imprima la fuente del siguiente, imprimamos (d2) en lugar de imprimir (d1) al final.
Pitón:
d1 = "code part of self" d2 = "code part of sibling" print('d1 =', repr(d1)); print('d2 =', repr(d2)); print(d2)
Ya sabemos que el contenido de d1 es solo una copia de la línea 3. Pero aún no tenemos el contenido de d2.
Digamos que queríamos crear un QuineRelay con JavaScript. Escribamos un intrón similar en JS.
JavaScript:
d1 = "code part of sibling" d2 = "code part of self" console.log(`d1 = ${JSON.stringify(d1)}`); console.log(`d2 = ${JSON.stringify(d2)}`); console.log(d1);
Ahora, la línea 3 del intrón JS anterior es el código del programa hermano que queríamos.
Peguen el código de cada uno como intrones en el otro.
Nota. Necesitamos agregar d1 '' en js para evitar algunas discrepancias en las citas
Python: ¡Pruébalo en línea!
d1 = "print('d1 =', repr(d1)); print('d2 =', repr(d2)); print(d2)" d2 = "console.log(`d1 = ${JSON.stringify(d1)}`); console.log(`d2 = ${JSON.stringify(d2)}`); console.log(d1 '');" print('d1 =', repr(d1)); print('d2 =', repr(d2)); print(d2)
JavaScript: ¡Pruébalo online!
d1 = "print('d1 =', repr(d1)); print('d2 =', repr(d2)); print(d2)" d2 = "console.log(`d1 = ${JSON.stringify(d1)}`); console.log(`d2 = ${JSON.stringify(d2)}`); console.log(d1 '');" console.log(`d1 = ${JSON.stringify(d1)}`); console.log(`d2 = ${JSON.stringify(d2)}`); console.log(d1 '');
Ahí lo tienes. ¡Es un QuineRelay de segundo orden adecuado! Un programa Python, que imprime un programa JavaScript, que imprime el programa Python original en un ciclo.
Crear un QuineRelay es un ejercicio de codificación creativa y comprensión de cómo los diferentes lenguajes representan y manipulan cadenas. Implica entrelazar intrones de varios programas, cada uno de los cuales contiene el código para replicar a su siguiente vecino.
En esencia, un relevo de enésimo orden es un juego de n formas inteligentes de escapar de comillas en n lenguajes de programación.
¡Estén atentos a la próxima publicación en MultiQuine!
Fuentes y referencias:
Descargo de responsabilidad: Todos los recursos proporcionados provienen en parte de Internet. Si existe alguna infracción de sus derechos de autor u otros derechos e intereses, explique los motivos detallados y proporcione pruebas de los derechos de autor o derechos e intereses y luego envíelos al correo electrónico: [email protected]. Lo manejaremos por usted lo antes posible.
Copyright© 2022 湘ICP备2022001581号-3