在 Quine 博客系列之前的冒险中,我们探索了如何编写我们自己的 Quine 和内含子。今天我们将了解 QuineRelays 是什么以及如何利用 Introns 来创建它们。
想象一圈程序,每个程序都用不同的语言编写。该循环中的每个程序都有一个目的:打印序列中下一个程序的源代码。最后一个程序通过打印第一个程序的源代码来关闭循环。
本质上,QuineRelays 是一组 n 个程序,采用 n 种不同的语言,例如:
让我们看一些例子来更好地理解这个概念。
这个二阶 QuineRelay 具有一个 JavaScript 程序,可以打印 Python 程序,然后打印回原始 JavaScript 程序。这是一对动态的自我复制组合。
JavaScript → Python ⥀
JavaScript:在线尝试!
console.log((q=_=>`print(${JSON.stringify(`console.log((q=${q+[]})())`)})`)())
Python:在线尝试!
print("console.log((q=_=>`print(${JSON.stringify(`console.log((q=${q+[]})())`)})`)())")
使用三阶 QuineRelay 会让事情变得更加有趣。这个从 Haskell 程序开始,输出 Python 程序,Python 程序输出 Ruby 程序,最后 Ruby 程序循环回原始 Haskell 程序。
Haskell → Python2 → Ruby ⥀
Haskell:在线尝试!
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:在线尝试!
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:在线尝试!
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)+')'")
这是一个四阶 QuineRelay:Ruby → Java → C# → Python ⥀
GitHub
不同文化之间有一些共同的象征意义。其中之一是衔尾蛇,它在埃及、希腊、罗马、印度教、西伯利亚、挪威、非洲和南美神话中都有提及。衔尾蛇是一个古老的符号,描绘了一条蛇或龙吞噬自己的尾巴,代表着创造和毁灭的永恒循环。
在北欧神话中,耶梦加得是一条巨蛇,是洛基和女巨人安格尔博达的中间的孩子。奥丁将耶梦加得扔进米德加德(人类王国)周围的海洋中,这条蛇在那里变得如此巨大,以至于它包围了世界并抓住了自己的尾巴。由于它围绕着米德加德(地球),因此被称为世界之蛇 - 衔尾蛇。耶梦加得释放尾巴是诸神黄昏(世界的最后之战)开始的标志之一。
Quine 中继非常巧妙地体现了这种象征意义,因为循环中的每个程序都会产生下一个程序,最后才会重生,因此被昵称为 Ouroboros 程序。
请坐在座位上。这是一个 128 阶 Ouroboros QuineRelay。是的,你没看错。 128!!!
Ruby → Rust → Scala → ...(其他 120 个)... → Python → R → Ratfor → rc → REXX ⥀
GitHub
好像这还不够令人印象深刻,它还包括一个复活节彩蛋。缩小后的原始 Ruby 代码包含一条 Ouroboros 龙!
让我们启动之前编写的Python内含子,尝试将其变成二阶QuineRelay。
Python Intron:在线尝试!
intron = 'wubbalubbadubdub' data = "print('intron =', repr(intron)); print('data =', repr(data)); print(data)" print('intron =', repr(intron)); print('data =', repr(data)); print(data)
利用内含子的魔力,我们现在可以轻松地将不同语言的同级奎因的代码部分放入内含子中。生成以下形式的程序:
Python:
intron = "code part of sibling" data = "code part of self" print('intron =', repr(intron)); print('data =', repr(data)); print(data)
因为,每个变量只是充当不同奎因的数据。让我们将 data 和 intron 分别重命名为 d1 和 d2。
Python:
d1 = "code part of self" d2 = "code part of sibling" print('d1 =', repr(d1)); print('d2 =', repr(d2)); print(d1)
现在,d2充当内含子,但上面的程序仍然尝试打印self的代码部分。为了让它打印下一个的源代码,让我们在最后打印(d2)而不是打印(d1)。
Python:
d1 = "code part of self" d2 = "code part of sibling" print('d1 =', repr(d1)); print('d2 =', repr(d2)); print(d2)
我们已经知道 d1 的内容只是第 3 行的副本。但是我们还没有 d2 的内容。
比如说,我们想用 JavaScript 创建一个 QuineRelay。我们用 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);
现在,上面 JS 内含子的第 3 行,就是我们想要的兄弟程序的 代码!
将彼此的代码粘贴为对方的内含子。
笔记。我们需要在 js 中添加 d1 + '' 以避免一些引用不匹配
Python: Try it 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 + '');" print('d1 =', repr(d1)); print('d2 =', repr(d2)); print(d2)
JavaScript: Try it 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 + '');
There you go. It's a proper 2nd order QuineRelay! A Python program, that prints a JavaScript program, that prints the original Python program back in a cycle.
Creating a QuineRelay is an exercise in creative coding and understanding how different languages represent and manipulate strings. It involves weaving together introns from various programs, each containing the code to replicate its next neighbour.
At its core, an nth-order relay is a game of n clever ways to escape quotes across n programming languages.
Stay tuned for the next post on MultiQuine!
Sources and references:
以上是QuineRelay:奎因蛇的诞生的详细内容。更多信息请关注PHP中文网其他相关文章!