1701066428
loop until x=4
1701066429
1701066430
{
1701066431
1701066432
print(“Hello, world!”)
1701066433
1701066434
x=x+1
1701066435
1701066436
}
1701066437
1701066438
会输出:
1701066439
1701066440
Hello, world!
1701066441
1701066442
Hello, world!
1701066443
1701066444
Hello, world!
1701066445
1701066446
Hello, world!
1701066447
1701066448
大括号之间的代码会反复执行直到循环结束条件(这里是x=4)满足。变量用作计数器——从0开始,每循环一次加1。增加到4时循环停止。
1701066449
1701066450
现在可以来看看自我复制程序了,程序完整展现在图8.2中。理解一段程序最好的办法就是手工推演,也就是一行一行跟踪程序的运行。
1701066451
1701066452
假设图8.2中的程序被加载到内存中,然后假设有人在计算机命令提示符后键入selfcopy,计算机就会开始执行程序selfcopy。译码器——操作系统的一部分——会将指令指针设为1,指向程序名。然后ip会下移,逐行执行各条指令。
1701066453
1701066454
在地址2处变量L被设为ip-1。而ip是当前执行指令的位置。因此当执行第2行时,ip设为2,L设为2-1=1。(注意虽然随着指令执行会不断变化,但L在重置之前会一直等于1直到其被重置。)接着会进入循环,直到line[L]等于字符串end。前面说了line[L]等于内存中地址L处的字符串。目前L等于1,line[L]等于字符串programselfcopy,不等于字符串end,因此循环不会停止。在循环中,会显示输出line[L],并将L加1。最初,L=1,显示输出program selfcopy;然后L被置为2。
1701066455
1701066456
1701066457
1701066458
1701066459
▲图8.2 自我复制的程序
1701066460
1701066461
现在,line[L]指的是程序第二行,即L=ip-1,仍然不等于end,因此循环会继续。这样程序就会被逐行输出。尤其有意思的是第5行:当L=5时,执行第5行,指令print(line[L])会显示输出其自身。当L=9时,line[L]等于end,循环终止。这时已经显示输出了1—8行。指令指针指向第8行(紧跟在循环后面的指令),执行时显示输出字符串“end”结束自我复制。在这个程序中自我复制的本质,是用两种方式来使用内存中的信息:既作为执行的指令,又作为这些指令使用的数据。正是对信息的双重使用让我们得以避开前面尝试自我复制程序时遇到的那种无穷反复。
1701066462
1701066464
自我复制程序的深层意义
1701066465
1701066466
信息的双重使用是哥德尔悖论的核心,他的自指句子“这个命题是不可证的”体现的正是这一点。
1701066467
1701066468
理解这个需要耍点把戏。首先,请注意这个句子同其他句子一样,可以从两个角度来看:①视为句子中包括的文字、空格符和标点组成的字符串;②视为字符串所代表的意义,同语言使用者的解读一样。
1701066469
1701066470
为了明确起见,我们将句子的字符串本身记为S。也就是说,S=“这个命题是不可证的”。现在可以陈述的一些命题:例如它包含9个字,1个句号。
1701066471
1701066472
句子的意义则记为M。我们可以将M重写为“命题S是不可证的”。某种程度上,你可以将M视为“指令”,而将S视为指令操作的数据。怪异(而又神奇)的是,数据S与指令M是同一个东西。哥德尔之所以能将句子转化为数学中的悖论,一个主要原因就是他能将M表示成数学命题,将S表示成编码那个数学命题字符串的数字。
1701066473
1701066474
这就是背后的把戏。侯世达在《哥德尔、艾舍尔、巴赫——集异璧之大成》一书中,对字符串与字符串的意义之间的区别,以及自指所导致的悖论,进行了详细而有趣的讨论。
1701066475
1701066476
与之类似,对信息的双重使用也是图灵对停机问题不可判定性证明的关键。还记得第4章的H和H′吗?记得H′是如何作用于自身的编码吗?同这里的自复制程序一样,H′也是以两种方式被使用:解释为程序,同时也作为程序的输入。
1701066477
[
上一页 ]
[ :1.701066428e+09 ]
[
下一页 ]