Quine 的存在性可以通过 Kleene's Second Recursion Theorem(克莱尼第二递归定理)证明:
对于任意可计算函数
$F$ ,存在一个程序$e$ ,使得$\phi_e = \phi_{F(e)}$ 。
在 Quine 的语境下,这保证了对于任意程序变换
Quine 与哥德尔不完备定理、停机问题都基于康托尔对角线论证(Cantor's Diagonal Argument):
假设所有程序可以枚举:P₁, P₂, P₃, ...
构造新程序 Q,使得 Q 在第 i 个位置与 Pᵢ 不同
则 Q 不在枚举中,矛盾!
Quine 实现了程序的自引用,类似于:
- 哥德尔语句:"这个命题不可证明"
- 理发师悖论
- 元胞自动机中的自我复制模式
Quine 的核心是代码即数据(Code is Data)的 Lisp 哲学:
# 数据部分(字符串)
code = 'print("Hello")'
# 代码部分(执行)
eval(code) # 将数据视为代码执行Quine 最大的技术挑战是转义引号:
# 错误:引号不匹配
s = "s = "s = ...""
# 正确:使用 %r 或 repr() 自动转义
s = 's=%r;print(s%%s)';print(s%s)标准 Quine 模板:
DATA = "..."
PROGRAM = PREFIX + ENCODE(DATA) + SUFFIX
输出 PROGRAM
其中 ENCODE(DATA) 必须满足:DECODE(ENCODE(X)) = X
| 语言特性 | 对 Quine 的影响 | 示例语言 |
|---|---|---|
eval() |
简化实现 | Python, JavaScript |
| 宏系统 | 元编程能力 | Lisp, Rust |
| 反射 | 自检查 | Java, Go |
| 无引号字符串 | 极简实现 | sed, shell |
| 图灵不完备 | 可能无法写 Quine | SQL(部分), HTML |
Brainfuck 没有字符串类型,必须用内存操作构建自复制:
->+>+++>>+>++>+>++>>+>+>+>++>>+>++>+>++>+>+>++>>+>->+>++>+>>+++>+>>++
...(Brainfuck Quine 通常非常长,因为需要手动构建 ASCII 码)
SQL 缺乏字符串操作,需要利用 REPLACE 或递归 CTE:
SELECT REPLACE('SELECT REPLACE("?", CHAR(34), "?")', CHAR(34), '"')标准 Quine 的时间复杂度是
- 朴素实现:$O(n)$ - 存储整个源代码
- 流式实现:$O(1)$ - 边生成边输出
Quine 与柯氏复杂度(Kolmogorov Complexity)密切相关:
字符串
$s$ 的柯氏复杂度$K(s)$ 是输出$s$ 的最短程序长度。
对于一个 Quine
定义:程序序列
-
$P_1$ 执行输出$P_2$ -
$P_2$ 执行输出$P_3$ - ...
-
$P_n$ 执行输出$P_1$
存在性证明:通过对角线构造法,对于任意
定义:程序
- 语言
$L_1$ 解释$P$ 输出$P$ - 语言
$L_2$ 解释$P$ 输出$P$ - ...
限制:取决于语言的语法兼容性。Python 2/3 是可能的,Python/JavaScript 极具挑战性。
本仓库中的 variants/ouroboros/py_chain_0.py 等文件给出了一个长度为
- 记程序序列为
$P_0, P_1, ..., P_{n-1}$ - 每个程序
$P_i$ 输出下一个程序的源码:$P_i \Rightarrow \mathrm{src}(P_{(i+1) \bmod n})$
可以定义算子
$T(P_0, ..., P_{n-1}) = (\widehat P_0, ..., \widehat P_{n-1})$ - 其中
$\widehat P_i$ 是“将$P_{(i+1) \bmod n}$ 的源码硬编码并打印出来”的程序
当存在元组
$(P_0, ..., P_{n-1}) = T(P_0, ..., P_{n-1})$
时,就得到一个多步不动点:不是单个程序满足
py_chain_k.py 系列正是这种构造的具体实例:每个节点内部都携带完整的链表 names = [...],通过索引轮换实现了这一固定点性质。
形式化定义:
程序
编码理论联系:这类似于纠错码(Error-Correcting Codes)。
| 计算机 Quine | DNA 复制 |
|---|---|
| 源代码 | DNA 双链 |
| 打印语句 | 聚合酶 |
| 转录/翻译 | 转录/翻译 |
| 突变 | 辐射/复制错误 |
康威生命游戏中存在自复制模式(Gemini),可以看作是二维的 Quine。
Quine 实现了程序的自我指涉(Self-Reference):
- 程序描述自身
- 类似于"这句话是假的"
Quine 展示了信息可以独立于载体:
- 同一个 Quine 可以在不同计算机上运行
- 输出相同的"本质"
写 Quine 更像是发现而非创造——它根植于计算理论的必然性。
- Kleene, S.C. "Introduction to Metamathematics" (1952)
- Hofstadter, D. "Gödel, Escher, Bach" (1979)
- Chaitin, G. "Algorithmic Information Theory" (1987)
- Turing Tar-pit:图灵完备但难以使用的语言
- Meta-circular Interpreter:用语言自身实现的解释器
- Homoiconicity:代码即数据的语言特性(Lisp)
避免引号问题:
# 使用 chr() 构造字符串
s = chr(115) + chr(61) + ...import codecs
code = "73633d..." # hex
eval(codecs.decode(code, 'hex').decode())import zlib, base64
data = base64.b64encode(zlib.compress(source))
exec(zlib.decompress(base64.b64decode(data)))-
最短 Quine 的界限:对于语言
$L$ ,最短 Quine 的长度是多少? -
抗辐射的极限:对于
$n$ 个字符的程序,最大能抵抗多少错误? - 多语言 Quine 的极限:最多能支持多少种语言?
- 量子 Quine:量子计算中的 Quine 会是什么样?
"An algorithm is a finite answer to an infinite number of questions."
—— Stephen Kleene