更改

跳到导航 跳到搜索
第171行: 第171行:  
虽然提起自指,人们很容易想到自指悖轮。但是,人们不熟悉的是另外一大类无害的自指,它们通常直接应用蒯恩技术,而实现某些意想不到的结构或者功能。下面,让我们先从一种最简单的建构性自指:自打印程序说起。
 
虽然提起自指,人们很容易想到自指悖轮。但是,人们不熟悉的是另外一大类无害的自指,它们通常直接应用蒯恩技术,而实现某些意想不到的结构或者功能。下面,让我们先从一种最简单的建构性自指:自打印程序说起。
   −
所谓的程序自打印就是指一个程序能够在不读取外部文件的条件下把自己的源代码打印出来。首先,我们要先领教一下,一个自我打印的程序是多么不可能的!我们知道,要写一个程序打印出“helloworld!”字样是非常容易的,例如:
+
所谓的程序自打印就是指一个程序能够在'''不读取外部文件'''的条件下把自己的源代码打印出来。首先,我们要先领教一下,一个自我打印的程序是多么不可能的!我们知道,要写一个程序打印出“helloworld!”字样是非常容易的,例如:
   −
Print(‘helloworld!’)
+
<code>Print(‘helloworld!’)</code>
    
注意在这个程序中,字符串都用单引号括起来。那么,我们能不能写一个程序,把这个打印“helloworld!”程序的源代码打印出来呢?这也是可以办到的,例如下面的程序:
 
注意在这个程序中,字符串都用单引号括起来。那么,我们能不能写一个程序,把这个打印“helloworld!”程序的源代码打印出来呢?这也是可以办到的,例如下面的程序:
   −
Print(‘Print(\’helloworld!\’)’)
+
<code>Print(‘Print(\’helloworld!\’)’)</code>
    
注意,这里面的“\’”会被编译器解释为一个字符串,这个字符串中就有一个字符:“'”。采用这个技巧,我们就可以解决如何在一个引号之中再输入一个引号的问题了。所以,我们可以很轻松地打印出这个能够打印”helloworld!”程序的程序源代码出来。但是很显然这个程序并不能打印出它自己,也许你会想到能不能打印出上面的程序源代码出来?当然可以!
 
注意,这里面的“\’”会被编译器解释为一个字符串,这个字符串中就有一个字符:“'”。采用这个技巧,我们就可以解决如何在一个引号之中再输入一个引号的问题了。所以,我们可以很轻松地打印出这个能够打印”helloworld!”程序的程序源代码出来。但是很显然这个程序并不能打印出它自己,也许你会想到能不能打印出上面的程序源代码出来?当然可以!
   −
Print(‘Print(\’Print(\\\’helloworld!\\\’)\’)’)
+
<code>Print(‘Print(\’Print(\\\’helloworld!\\\’)\’)’)</code>
    
其中\\就表示包含一个字符“\”的字符串变量,这样Print(‘\\’)就会打印出一个字符“\”,而Print(‘\\\’’)就会打印出字符串“\’”出来。所以,引号里面可以放入任意层次的引号。
 
其中\\就表示包含一个字符“\”的字符串变量,这样Print(‘\\’)就会打印出一个字符“\”,而Print(‘\\\’’)就会打印出字符串“\’”出来。所以,引号里面可以放入任意层次的引号。
第187行: 第187行:  
但是这个程序仍然不能打印自己!你很快发现,我们人类是写不出这种能够打印自己的程序的,因为它包含了无穷递归。不过,通过蒯恩技巧,实际上我们完全可以写出来一个自打印程序,如下:
 
但是这个程序仍然不能打印自己!你很快发现,我们人类是写不出这种能够打印自己的程序的,因为它包含了无穷递归。不过,通过蒯恩技巧,实际上我们完全可以写出来一个自打印程序,如下:
   −
S(x){q=’S(x){\\nq=\\\’\’+q+\’\\\’;\\nPrint(\\\’\’+p(q)+\’\\\’);\\n}’;Print(‘S(x){\nq=\’’+q+’\’;\nPrint(\’’+p(q)+’\’);\n}’);
+
<code>
 +
S(x){
 +
    q=’S(x){\\nq=\\\’\’+q+\’\\\’;\\nPrint(\\\’\’+p(q)+\’\\\’);\\n}’;
 +
    Print(‘S(x){\nq=\’’+q+’\’;\nPrint(\’’+p(q)+’\’);\n}’);
 
}
 
}
 +
</code>
 +
 
源代码1:自打印程序源代码
 
源代码1:自打印程序源代码
  

导航菜单