奎因程序,或称奎因,是一种在执行时能打印自身源代码的程序。 奎因程序不得 "跳出自身",例如打印其所在文件的内容,或使用内省功能打印自身表示。 相反,它必须计算自身的源代码。
创建此类程序的经典方法有两个步骤:
- 用插值占位符初始化一个字符串变量。
- 打印字符串并将其插值到自身。
诀窍在于使字符串恰到好处。 如何做到这一点因语言而异,取决于变量的声明、分号和换行的需要、所需的引号等。
巴什
与 Bash 中的大多数程序一样,该程序使用了一个有趣的怪癖。 虽然单引号是强引号,不会扩展任何内容,但 printf
八进制转义字符作为指定码位的字符:
s='s=%s;printf "$s" "$s"';printf "$s" "$s"
Python
在 Python 中,格式标识符 %r
最简单的方法是用换行符结束代码:
s='s=%r;print(s%%s)';print(s%s)
如果希望代码不换行,则必须编写如下内容:
s='s=%r;print(s%%s,sep="")';print(s%s,sep="")
的JavaScript
以下 JavaScript 函数在 node.js 下运行,它们使用 console.log
, 总是添加新行,因此每个脚本末尾都需要添加新行:
s="s=%j;console.log(s,s)";console.log(s,s)
下面的程序也很有趣:它没有打印整个表示法,但它依赖于函数具有特定表示法这一事实:
(function a(){console.log('('+a+')()')})()
下一个例子近乎作弊,因为它 eval
中古:
code='var q=unescape("%27");console.log("code="+q+code+q+";eval(code)")';eval(code)
生锈
Rust 提供了在格式化打印宏中引用参数的方法,但该宏要求打印宏的第一个参数是字符串字面量!因此,最好使用位置参数标识符:
fn main(){print!("fn main(){{print!({0:?},{0:?})}}","fn main(){{print!({0:?},{0:?})}}")}
的PHP
该 PHP 程序的工作原理是将源代码保存在字符串中,然后使用 printf
"(《世界人权宣言》) 39
代表 ASCII 字符 '
, 以正确处理字符串中的倒逗号:
<?php
$code = '<?php
$code = %c%s%c;
printf($code, 39, $code, 39);
';
printf($code, 39, $code, 39);
HQ9+
最后是由 Cliff Biffle 开发的 HQ9+:
Q