1986 年 RMS 在瑞典皇家理工学院 (KTH) 的演讲
理查德·斯托曼 (Richard Stallman) 于 1986 年 10 月 30 日在斯德哥尔摩皇家理工学院 (Kungliga Tekniska Högskolan) 的演讲稿,由学生社团 Datorföreningen Stacken 安排。
注:这是演讲稿的略微编辑版本。因此,它包含口语中自然的但在印刷中看起来很奇怪的错误开头和措辞。如何在不破坏原始演讲的情况下将其更正为书面英语风格尚不清楚。
Rms:看来大家想让我谈论三件事。一方面,我认为对于黑客俱乐部来说,最好的话题是早期的麻省理工学院是什么样的。是什么让人工智能实验室成为一个如此特别的地方。但人们也告诉我,由于这里的人与周一和周二会议上的人完全不同,我应该谈谈 GNU 项目的进展,并且我应该谈谈为什么软件和信息不能被拥有,这意味着总共三个话题,由于其中两个主题各花了一个小时,这意味着我们将会花费相当长的时间。所以我想,也许我可以把它分成三个部分,人们可以出去参加他们不感兴趣的部分,然后当我到达一个部分的结尾时,我可以说是结尾了,人们可以出去,我可以派 Jan Rynning 出去把其他人带进来。
[其他人说:“Janne, han trenger ingen mike.”(翻译:“Janne,他不需要麦克风。”)]
Jan,你准备好跑出去把其他人带回来吗?
Jmr:我正在找麦克风,有人告诉我它在这把锁着的盒子里。
Rms:在人工智能实验室的早期,我们会拿起大锤把它砸开,破碎的门会给那些敢于锁住人们需要使用的东西的人一个教训。幸运的是,我曾经学习保加利亚歌曲,所以我使用麦克风毫无问题。
无论如何,我应该设置这个系统来通知您关于演讲的各个部分,还是您只是喜欢坐着听完所有内容?[回答:耶!]
我开始编程时,是 1969 年,我在纽约的一个 IBM 实验室里工作。之后,我上了一所设有计算机科学系的学校,这可能和大多数学校一样。有一些教授负责应该做什么,还有一些人决定谁可以使用什么。大多数人都没有足够的终端,但许多教授在自己的办公室里都有自己的终端,这是一种浪费,但这很能代表他们的态度。当我参观麻省理工学院的人工智能实验室时,我发现了一种与此截然不同的精神。例如:那里,终端被认为是属于大家的,教授把它们锁在办公室里会发现他们的门被打破。我实际上看到一辆车上有一个大铁块,那是用来打破一位教授的办公室门的,因为他竟敢锁住一个终端。那时终端非常少,这个系统大概只有五个显示终端,所以如果其中一个被锁起来,那将是一场相当大的灾难。
在随后的几年里,我受到了这些想法的启发,我多次爬过天花板或地板下,去打开装有人们需要使用的机器的房间,我通常会留下一张纸条,向人们解释他们不应该如此自私地锁门。锁门的人基本上只考虑自己。他们当然有理由,他们认为有些东西可能会被偷,他们想把它锁起来,但他们不在乎锁住同一个房间的其他东西会影响其他人。几乎每次发生这种情况时,一旦我让他们意识到,是否应该锁上房间不仅仅取决于他们,他们就能够找到一个折衷的解决方案:一些其他地方来放置他们担心的东西,他们可以锁上的桌子,另一个小房间。但重点是人们通常不会费心去考虑这一点。他们有这样的想法:“这个房间是我的,我可以把它锁起来,管别人去死”,这正是我们必须教导他们不要有的精神。
但这种打开门的精神并不是孤立的,它是整个生活方式的一部分。人工智能实验室的黑客们真的热衷于编写好的程序和有趣的程序。正是因为他们如此渴望完成更多的工作,他们才不会容忍终端被锁起来,或者人们可以做的许多其他阻碍有用的工作的事情。那些真正关心自己想要做的事情的高士气的人,与那些认为这只是一份工作的人之间的区别。如果这只是一份工作,谁会在乎雇佣你的人是如此愚蠢,以至于他们让你坐着等待,这是他们的时间,他们的钱,但在这样的地方不会完成多少工作,而且在这种地方工作没什么乐趣。
我们在人工智能实验室也没有文件保护。计算机上根本没有安全措施。我们有意识地希望如此。编写不兼容分时系统的黑客们认为,文件保护通常被自封的系统管理员用来获得对其他所有人的权力。他们不希望任何人能够通过这种方式获得对他们的权力,所以他们没有实现这种功能。结果是,每当系统中的某些东西出现故障时,您总能修复它。你永远不必因为“无能为力”而沮丧地坐在那里,因为你确切地知道问题出在哪里,而且有人决定他们不相信你来做这件事。您不必放弃回家,等待某人在早上来修复系统,而您比他更清楚需要做什么。
我们也不允许任何教授或老板决定要做什么工作,因为我们的工作是改进系统!当然,我们会与用户交谈;如果您不这样做,您就无法知道需要什么。但在那之后,我们最能看到哪些改进是可行的,我们总是互相交谈我们希望如何改变系统,以及我们在其他系统中看到的哪些巧妙的想法可能可以利用。因此,我们的结果是拥有一个运行平稳的无政府状态,而且在我的经历之后,我确信这是人们生活的最佳方式。
不幸的是,这种形式的人工智能实验室被摧毁了。多年来,我们一直担心人工智能实验室会被麻省理工学院的另一个实验室——计算机科学实验室所摧毁,该实验室的主任是一个帝国建造者,他竭尽所能地在麻省理工学院内部获得晋升,并使他的组织更大,他不断试图使人工智能实验室成为他的实验室的一部分,没有人愿意按照他的方式做事,因为他认为人们应该服从命令等等。
但是我们设法抵御了这种危险,结果却被我们从未预料到的事情所摧毁,那就是商业主义。在 80 年代初,黑客们突然发现,他们正在做的事情现在有了商业利益。在一家私营公司工作可能会变得富有。所需要做的就是停止与世界其他地方分享他们的工作,并摧毁麻省理工学院的人工智能实验室,而这正是他们所做的,尽管我尽一切努力来阻止他们。
基本上,除了我之外,人工智能实验室所有有能力的程序员都被挖走了,这不仅造成了暂时的变化,还造成了永久性的转变,因为它打破了黑客文化的连续性。新的黑客总是被老黑客所吸引;那里有最有趣的计算机和做最有趣事情的人,以及一种非常有趣的参与其中的精神。一旦这些东西消失了,就没有什么可以推荐给新人的了,所以新人停止到来。没有人可以让他们受到启发,没有人可以让他们学习这些传统。此外,也没有人可以学习如何做好编程。只有一群教授和研究生,他们真的不知道如何使程序工作,您无法学习如何使好的程序工作。所以我所爱的人工智能实验室已经不复存在了,经过几年的与那些这样做的人作斗争以试图惩罚他们之后,我决定我应该致力于尝试建立一个具有这种精神的新社区。
但我必须面对的问题之一是专有软件的问题。例如,在黑客离开实验室后,实验室发生了一件事,就是我们开发的机器和软件无法再进行维护。当然,软件可以工作,如果没人改动它,它会继续工作,但机器不行。机器会坏,没有人可以修理它们,最终它们会被扔掉。过去,是的,我们有机器的维修合同,但这基本上是个笑话。这是一种在人工智能实验室的专家黑客修好问题后获得零件的方法。因为如果你让现场维修人员修理,他们会花上几天的时间,而你不想那样,你希望它能工作。所以,那些知道如何做这些事情的人会直接去快速修理好它,而且由于他们比任何现场维修人员都胜任十倍,他们可以做得更好。然后他们会把坏掉的电路板留在那儿,并告诉现场维修人员“把这些带回去,给我们一些新的。”
在更早的时期,我们的黑客过去也会修改来自数字设备公司的机器。例如,他们在PDP-10上构建了分页盒。现在我认为这里[在斯德哥尔摩]也有人做这些事情,但在当时这相当不寻常。而在更早的时期,1960年代初,人们过去会修改计算机,添加各种新的指令和新的花哨的分时功能,因此在麻省理工学院的PDP-1在七十年代中期退役时,它的指令数量大约是数字设备公司在六十年代初交付时的两倍,并且它有特殊的硬件调度辅助功能和奇怪的内存映射功能,可以将单个硬件设备分配给特定的分时作业,还有很多我几乎不了解的东西。我认为他们还构建了一些扩展的寻址模式,他们添加了索引寄存器和间接寻址,基本上把它从一台弱机变成了一台半合理的机器。
我想,超大规模集成电路的一个缺点是,在你的机器上添加指令不再那么可行了。
PDP-1还有一个非常有趣的特点,就是可以用非常少的指令编写有趣的程序。比此后的任何机器都少。我相信,例如,著名的显示黑客“吞噬的方块”,它会生成越来越大的方块,然后分解成许多较小的方块,这些方块会越来越大,然后分解成较小的方块。它在PDP-1上是用大约五个指令编写的。许多其他漂亮的显示程序可以用少量指令编写。
这就是人工智能实验室。但是,除了他们的无政府主义之外,黑客的文化是什么样的呢?在PDP-1时代,最初至少只有一个人可以使用机器。几年后,他们编写了一个分时系统,并为此添加了许多硬件。但在开始时,你只需要注册一些时间。现在,当然,教授和从事官方项目的学生总是在白天来。因此,那些想要获得大量时间的人会在晚上竞争较少的时候注册时间,这形成了黑客在晚上工作的习惯。即使在有了分时之后,仍然更容易获得时间,你可以在晚上获得更多的周期,因为用户更少。因此,那些想要完成大量工作的人仍然会在晚上来。但那时它开始变成另一回事,因为你不是独自一人,还有一些其他的黑客在那里,所以它变成了一种社会现象。白天如果你来,你可能会发现教授和学生并不真正热爱这台机器,而在晚上如果你来,你会发现黑客。因此,黑客晚上来是为了与他们的文化在一起。他们还发展了其他传统,例如凌晨三点吃中餐。我记得许多在唐人街回来的路上从车里看到的日出。看到日出实际上是一件非常美好的事情,因为这是一天中非常平静的时刻。这是一天中准备睡觉的美好时刻。在光明刚刚亮起,鸟儿开始鸣叫时走回家真是太好了,你可以对你那天晚上所做的工作有一种真正的、温柔的满足感和宁静感。
我们开始的另一个传统是在实验室里有睡觉的地方。自从我第一次在那里以来,实验室里总是有至少一张床。而且我可能比大多数人在实验室里生活的时间更多,因为每隔一两年,由于某种原因,我都会没有公寓,并且会在实验室里住上几个月。而且我一直觉得它很舒适,而且在夏天也很凉爽。但发现有人在实验室睡着并不罕见,这又是由于他们的热情;你会尽可能地熬夜进行黑客攻击,因为你就是不想停下来。然后当你完全筋疲力尽时,你会爬到最近的柔软水平面上。一种非常非正式的氛围。
但是,当黑客都离开实验室后,这导致了人口结构的变化,因为那些并不真正热爱这台机器的教授和学生和以前一样多,所以他们现在是主要群体,而且他们非常害怕。他们说,没有黑客来维护系统,“我们将面临一场灾难,我们必须使用商业软件,”他们说“我们可以期望公司来维护它。”事实证明他们完全错了,但他们就是这么做的。
这正是新的KL-10系统应该到达的时候,问题是,它会运行不兼容分时系统还是运行数字设备公司的Twenex系统。一旦可能支持使用ITS的黑客离开后,学术界人士选择运行商业软件,这产生了几个直接的影响。其中一些实际上不是那么直接,但是它们是必然的结果,任何思考过它的人都会看到。
其中一件事是,该软件编写得更差,更难理解;因此,人们更难进行实际需要的更改。另一件事是,该软件附带了安全性,这不可避免地导致人们彼此合作减少。在过去,在ITS上,每个人都可以查看任何文件、更改任何文件被认为是可取的,因为我们有理由这样做。我记得一件有趣的丑闻,有人发送了一个关于如何使用Macsyma的求助请求。Macsyma是麻省理工学院开发的符号代数程序。他向其中一位从事该工作的人发送了一个求助请求,几个小时后,他收到了来自其他人的回复。他很震惊,他发送了一条消息“某某人一定是在看你的邮件,难道邮件文件在你的系统上没有得到适当的保护吗?”“当然,在我们的系统上,没有文件是受保护的。有什么问题?你更快地得到了答案;你为什么不高兴?当然,我们会阅读彼此的邮件,这样我们才能找到像你这样的人并帮助他们。”有些人就是不知道自己什么时候过得很好。
但是,当然,Twenex不仅具有安全性,并且默认情况下开启了安全性,而且它的设计前提是安全性正在使用中。因此,有很多很容易做的事情会导致很多损害,而唯一可以阻止你意外地做这些事情的就是安全性。在ITS上,我们发展了其他方法来阻止人们意外地做这些事情,但在Twenex上你没有这些方法,因为他们假设将会有严格的安全措施生效,只有老板才有权这样做。所以他们没有加入任何其他机制来防止意外发生。结果是,你不能只是使用Twenex并关闭安全性,就能获得你真正想要的东西,而且不再有黑客来更改并加入这些其他机制,所以人们被迫使用安全性。大约在机器到位六个月后,他们开始发生一些政变。也就是说,起初我们假设为实验室工作的所有人都将拥有wheel位,该位赋予了覆盖所有安全措施的全部权力,但是有一天下午,你会发现几乎所有人的wheel位都被关闭了。
当我发现这些时,我推翻了他们。第一次,我碰巧知道其中一位精英成员的密码,所以我能够用它来重新开启所有人的权限。第二次,他更改了他的密码,他现在改变了他的立场,他现在是贵族党的一员。所以,我不得不把机器关掉,使用非分时的DDT来四处窥探。我在监视器中四处窥探了一会儿,最终弄清楚了如何让它加载并让我修补它,以便我可以关闭密码检查,然后我重新开启了一大批人的wheel位,并发布了一条系统消息。我必须解释一下,这台机器的名字是OZ,所以我发布了一条系统消息说:“又有人试图夺取政权。到目前为止,贵族势力已经被击败——自由OZ电台。”后来我发现“自由OZ电台”是Firesign Theater使用的一个东西。当时我并不知道。
但是,情况逐渐变得越来越糟,只是系统的构建方式迫使人们要求越来越多的安全性。直到最终我被迫停止使用这台机器,因为我拒绝使用秘密的密码。自从密码第一次出现在麻省理工学院人工智能实验室以来,我得出结论,为了捍卫我的信念,为了遵循我的信念,即不应该有密码,我应该始终确保拥有一个尽可能明显的密码,并且我应该告诉所有人它是什么。因为我不认为在计算机上设置安全性是真正可取的,所以我应该不愿意帮助维护安全制度。在允许的系统上,我使用“空密码”,而在不允许使用该密码的系统上,或者在意味着你根本无法从其他地方登录的情况下,我使用我的登录名作为我的密码。它就像你能想到的那样明显。当人们指出这样人们可能会以我的身份登录时,我说“是的,这就是目的,有人可能需要从这台机器上获取一些数据。我想确保他们不会被安全措施搞砸。”
我总是做的另一件事是,我总是关闭我的目录和文件上的所有保护,因为我不时在那里存储有用的程序,如果出现错误,我希望人们能够修复它。
但那台机器的设计初衷并非为了支持所谓的“旅游”现象。现在,“旅游”是人工智能实验室一个非常古老的传统,它与我们其他的无政府主义形式并行,那就是我们会让外人来使用机器。在过去,任何人都可以走到机器前,以任何他喜欢的身份登录,这是自然而然的事情:如果你来参观,你就可以登录并工作。后来,当Arpanet开始出现,人们开始从全国各地连接到我们的机器时,我们将此稍微正式化了一些,将其作为一种被接受的传统。我们当时希望这些人实际上能够学会编程,并开始修改操作系统。如果你在其他地方对系统管理员说这些,他会感到震惊。如果你建议任何外人可以使用机器,他会说“但是如果他开始更改我们的系统程序怎么办?” 但是对我们来说,当外人开始更改系统程序时,这意味着他真正有兴趣成为社区的贡献者。我们总是鼓励他们这样做。当然,首先是从编写新的系统实用程序开始,小型的,然后我们会检查他们所做的并进行纠正,然后他们会继续为现有的、大型的实用程序添加功能。这些程序已经存在了十年或十五年,随着一个又一个工匠添加新功能而一点点增长。
有点像法国的城市,你可以看到非常古老的建筑,以及几百年后一直到现在的各种扩建部分。在计算机领域,一个在 1965 年开始的程序基本上就是这样。所以我们总是希望游客能成为系统维护者,或许他们之后会被聘用,在他们已经开始从事系统程序工作并向我们展示他们有能力做好工作之后。
但是 ITS 机器还有其他一些功能可以帮助防止这种情况失控,其中之一就是“间谍”功能,任何人都可以观看其他任何人在做什么。当然,游客喜欢间谍活动,他们认为这很酷,有点不正经,但结果是,如果任何游客开始做任何引起麻烦的事情,总会有人在看着他。所以很快他的朋友们就会非常生气,因为他们知道旅游业的持续存在取决于游客的责任感。所以通常会有人知道那个人是谁,我们可以让他离开我们。如果我们不能,那么我们就会暂时完全关闭来自某些地方的访问,当我们重新打开时,他就会离开并忘记我们了。就这样持续了很多年。
但是 Twenex 系统并非为此类事情而设计,最终他们无法容忍我使用每个人都知道的密码,游客总是以我的身份一次登录两三个,所以他们开始清空我的帐户。那时我主要在其他机器上工作,所以最终我放弃了,不再打开它了。事情就是这样。我没有以我自己的身份登录过那台机器…… [此时 RMS 被巨大的掌声打断。] ……为了。
但是当他们第一次获得这个 Twenex 系统时,他们想做一些改变。更改安全性的工作方式。他们还想让机器同时连接到 ARPA 网络和 MIT-chaos 网络,结果证明他们无法做到这一点,他们找不到足够有能力做出此类更改的人。没有足够的人才来做这件事,而且改变太难了。那个系统更难理解,因为它写得太差了,当然,Digital 不会做这些事情,所以他们的认为商业系统基本上可以自我维护的想法被证明是错误的。他们同样需要系统黑客,但他们不再有手段来吸引系统黑客。如今,在麻省理工学院,对黑客 ITS 感兴趣的人比对黑客 Twenex 感兴趣的人更多。
最终导致这种情况的另一个原因是,Twenex 无法共享。Twenex 是一个专有程序,只有当你以某些令人不快的秘密方式保守它时,才允许你获得源代码,这让它有一种糟糕的味道。除非一个人对此毫不在意(在计算机领域有些人是这样,有些人会做任何有趣的事情,而不会考虑一下他们是否在与其他人合作,但你必须非常粗心才会注意不到在这样的程序上工作是多么可悲的一件事,这进一步打击了人们的热情)。如果这还不够,那么每年左右他们都会给你一个新的版本,其中包含 50,000 行额外的代码,这些代码都是由猴子编写的。因为他们通常遵循“百万只猴子打字,最终会产生有用的东西”的系统开发理念。
我从我看到这些专有系统发生的事情中清楚地看到,我们拥有旧人工智能实验室精神的唯一方法是拥有一个自由操作系统。拥有一个由可以与任何人共享的自由软件组成的系统。这样我们就可以邀请所有人加入进来改进它。这就是导致 GNU 项目的原因。所以我想我们已经到了演讲的第二部分。
大约三年半前,我清楚地意识到我应该开始开发一个自由软件系统。我可以看到两种可能的系统可以开发:一种:类似于 LISP 机器的系统,本质上是一个与刚刚开发的 MIT LISP 机器系统完全相同的系统,只是它是免费的,并且在通用硬件上运行,而不是在特殊的 LISP 机器上运行。另一种可能性是更传统的操作系统,我很清楚,如果我做一个传统的操作系统,我应该让它与 Unix 兼容,因为这将使各地的人们更容易切换到它。过了一段时间,我得出结论,我应该做后者,原因是,我看到你不可能在通用硬件上拥有真正像 LISP 机器系统那样的东西。LISP 机器系统使用特殊的硬件加上特殊的可写微码来获得良好的执行速度和强大的运行时错误检测能力,特别是数据类型错误。为了让 LISP 系统在普通硬件上运行得足够快,你必须开始做出假设。假设某个参数是正确的类型,如果不是,系统就会崩溃。
当然,你可以加入显式检查,如果你愿意,你可以编写一个健壮的程序,但事实是,当你给一个函数提供错误类型的参数时,如果你没有加入检查它的东西,你将会遇到诸如内存寻址错误之类的问题。
所以结果是你需要在 LISP 系统下运行一些东西来捕获这些错误,并让用户能够继续运行,并调试他发生了什么。最后,我得出结论,如果我必须在较低级别有一个操作系统,我最好还是做一个好的操作系统——这是在操作系统和 lisp 之间进行选择,或者只是一个操作系统;因此我应该先做操作系统,并且应该让它与 Unix 兼容。最后,当我意识到我可以使用英语中最有趣的词作为这个系统的名称时,我很清楚我必须做出什么选择。这个词当然是 GNU,它代表“GNU's Not Unix”。递归首字母缩略词是麻省理工学院黑客社区中非常古老的传统。我相信它始于一个名为 TINT 的编辑器,意思是:“Tint Is Not Teco”,后来它经历了诸如“SINE”代表“SINE Is Not Emacs”,“FINE”代表“Fine Is Not Emacs”,“EINE”代表“Eine Is Not Emacs”和“ZWEI”代表“Zwei Was Eine Initially”等名称,最终到达了 GNU。
我想说,自从大约两年半前我真正开始从事 GNU 工作以来,我已经完成了超过一半的工作。当我准备开始这个项目时,我首先开始寻找我能找到的现有的免费资源。我发现了一个有趣的便携式编译器系统,它被称为“自由大学编译器工具包”,我想,有了这样的名字,也许我可以使用它。所以,我给开发它的人发了一条消息,问他是否愿意把它给 GNU 项目,他说“不,大学可能是自由的,但他们开发的软件不是”,但他接着说他也想要一个与 Unix 兼容的系统,并且他想为此编写一个内核,那么我为什么不编写实用程序呢,它们可以和他专有的编译器一起分发,以鼓励人们购买该编译器。我认为这是卑鄙的,所以我告诉他我的第一个项目将是一个编译器。
当时我真的不太了解优化编译器,因为我从未从事过这方面的工作。但是我得到一个编译器,当时有人告诉我它是免费的。这是一个名为 PASTEL 的编译器,作者说它的意思是“偏色的 PASCAL”。
Pastel 是一种非常复杂的语言,包含参数化类型和显式类型参数等许多复杂的功能。编译器当然是用这种语言编写的,并且有很多复杂的功能来优化这些功能的使用。例如:该语言中的“string”类型是一种参数化类型;如果你想要特定长度的字符串,你可以说string(n)
;你也可以只说string
,参数将从上下文中确定。现在,字符串非常重要,并且很多使用它们的构造都需要快速运行,这意味着它们必须具有很多功能来检测诸如:当字符串的声明长度是一个在函数中已知为常量的参数时,保存该值并优化它们将生成的代码,有很多复杂的事情。但是,我确实在这个编译器中看到了如何进行自动寄存器分配,以及一些关于如何处理不同类型机器的想法。
嗯,既然这个编译器已经编译了 PASTEL,我需要做的就是添加一个 C 的前端,我做了;并为 68000 添加一个后端,我希望它成为我的第一个目标机器。但是我遇到了一个严重的问题。由于 PASTEL 语言被定义为不要求你在使用之前声明,声明和使用可以以任何顺序进行,换句话说:Pascal 的 forward
声明已经过时了,因为这个原因,有必要读取整个程序,并将其保存在核心内存中,然后一次性处理。结果是,编译器中使用的中间存储,所需内存的大小,与文件的大小成正比。这还包括栈空间,你需要大量的栈空间,结果我发现:我可用的 68000 系统无法运行该编译器。因为它是一个糟糕的 Unix 版本,它给你大约 16K 字的堆栈限制,尽管机器中有 6 兆字节,但你只能有 16K 字的堆栈或类似的东西。当然,为了生成冲突矩阵,以查看哪些临时值与哪些其他值冲突或同时存活,它需要一个二次位矩阵,对于大型函数,这将使其达到数十万字节。所以我设法调试了编译器的十个或更多个过程中的第一个过程,交叉编译到该机器上,然后发现第二个过程永远无法运行。
当我思考如何解决这些问题,并想知道我是否应该尝试修复它们还是编写全新的编译器时,我以一种迂回的方式开始研究 GNU Emacs。GNU Emacs 是 GNU 系统的主要分发部分。它是一个可扩展的文本编辑器,很像我十年前开发的原始 Emacs,除了这个使用实际的 LISP 作为其扩展语言。编辑器本身是用 C 实现的,LISP 解释器也是如此,因此 LISP 解释器是完全可移植的,你不需要编辑器外部的 LISP 系统。编辑器包含自己的 LISP 系统,所有的编辑命令都是用 LISP 编写的,以便它们可以为你提供示例,供你查看如何编写自己的编辑命令,以及可以开始使用的东西,这样你就可以将它们更改为你真正想要的编辑命令。
在那年的夏天,大约是两年前,我的一个朋友告诉我,由于他在 Gosling Emacs 早期开发中的工作,他得到了 Gosling 的许可,在他收到的消息中,可以分发他的版本。Gosling 最初建立了他的 Emacs 并免费分发它,并让很多人帮助开发它,期望基于 Gosling 自己在他自己的手册中的话,他将遵循我开始使用原始 Emacs 的相同精神。然后他背叛了所有人,对其设置了版权,让人们承诺不重新分发它,然后将其出售给一家软件公司。我后来与他个人的交往表明,他就像你从那段历史中期望的那样胆小和卑鄙。
但无论如何,我的朋友给了我这个程序,我的目的是在顶层更改编辑命令,使其与我习惯的原始 Emacs 兼容。并使它们处理所有可能的数字参数组合等等,并具有我想要的所有功能。但是,在做了一点点之后,我发现该编辑器的扩展语言,称为 MOCKLISP,不足以完成这项任务。我发现我必须立即替换它才能做我计划要做的事情。在我有有一天也许可以用真正的 LISP 替换 MOCKLISP 的想法之前,我发现它必须首先完成。现在,MOCKLISP 之所以被称为 MOCK,是因为它没有任何结构数据类型:它没有 LISP 列表;它没有任何类型的数组。它也没有 LISP 符号,即带有名称的对象:对于任何特定的名称,只有一个对象,因此你可以键入该名称,并且总是返回相同的对象。这极大地阻碍了许多类型程序的编写,你必须通过复杂的字符串操作来完成那些实际上并非如此的事情。
所以我编写了一个 LISP 解释器并将其替换了 MOCKLISP,在此过程中,我发现我必须重写编辑器的许多内部数据结构,因为我希望它们是 LISP 对象。我希望 LISP 和编辑器之间的接口是清晰的,这意味着诸如编辑器缓冲区、子进程、窗口和缓冲区位置之类的对象都必须是 LISP 对象,以便对它们进行操作的编辑器原语实际上可以用 LISP 数据作为 LISP 函数调用。这意味着我必须重新设计所有这些对象的数据格式并重写所有对它们进行操作的函数,结果是大约六个月后,我几乎重写了编辑器中的所有内容。
此外,由于使用 MOCKLISP 编写东西如此困难,所有用 MOCKLISP 编写的东西都非常不干净,通过重写它们以利用真正的 LISP 的强大功能,我可以使它们更强大、更简单、更快。所以我做了,结果是当我开始分发这个程序时,我收到的东西只剩下一小部分。
此时,Gosling 认为他将该程序卖给的公司质疑我朋友分发它的权利,而且该消息在备份磁带上,因此他找不到它。而 Gosling 否认曾给他许可。然后发生了一件奇怪的事情。他正在与这家公司谈判,似乎该公司主要关心的是不要分发任何类似于他们正在分发的东西。你看,他仍在分发,他工作过的公司,也就是 Megatest,仍在分发他给我的相同东西,这实际上是旧版本的 Gosling Emacs 和他的更改,因此他将与他们达成协议,他将停止分发该版本,并将切换到使用 GNU Emacs,然后他们将承认他实际上拥有许可,然后据说每个人都会高兴。这家公司正在与我谈论希望分发 GNU Emacs,当然是免费的,但也出售各种支持服务,他们想雇用我来帮忙做这项工作。所以有点奇怪的是,他们后来改变了主意,拒绝签署该协议,并在网络上发布了一条消息,说我不允许分发该程序。他们实际上并没有说他们会采取任何行动,他们只是说不确定他们是否将来会做些什么。这足以吓到人们,让任何人都不再使用它了,这真是一件令人悲伤的事情。
(有时我想,也许我一生中可以做的最好的事情之一就是:找到一大堆属于商业秘密的专有软件,然后开始在街角分发副本,这样它就不再是商业秘密了,也许这比我自己编写它更有效地为人们提供新的免费软件;但是每个人都太胆小了,甚至不敢拿它。)
所以我被迫重写了剩下的所有内容,我做到了,这花了我大约一个半星期。所以他们赢得了巨大的胜利。我当然在那之后永远不会以任何方式与他们合作。
然后在 GNU Emacs 相当稳定之后,这总共花了一年半左右的时间,我开始回到系统的其他部分。我开发了一个名为 GDB 的调试器,它是 C 代码的符号调试器,最近已经开始分发。现在,这个调试器在很大程度上秉承了 DBX 的精神,DBX 是伯克利 Unix 自带的调试器。命令由一个表示你想要做什么的词组成,后跟参数。在这个调试器中,所有命令都可以缩写,常用命令都有单字符缩写,但总是允许任何唯一的缩写。有可扩展的 HELP 功能,你可以键入 HELP,后跟任何命令甚至子命令,并获得有关如何使用该命令的详细说明。当然,你可以键入任何 C 表达式,它会打印该值。
你还可以做一些在符号 C 调试器中不常见的事情,例如:你可以引用任何内存地址的任何 C 数据类型,以检查值或分配值。因此,例如,如果你想在某个地址的字中存储一个浮点值,你只需说:“给我该地址的 FLOAT 或 DOUBLE 类型的对象”,然后赋值。你可以做的另一件事是检查过去检查过的所有值。每个检查的值都会放在“值历史”中。你可以通过其数字位置引用历史记录中的任何元素,或者你可以轻松地使用美元符号引用最后一个元素。这使得跟踪列表结构变得更加容易。如果你有任何包含指向另一个结构的指针的 C 结构,你可以执行类似 PRINT *$.next
的操作,它表示:“从你上次向我展示的东西中获取下一个字段,然后显示它指向的结构。”你可以重复该命令,每次你都会看到列表中的下一个结构。然而,在我见过的所有其他 C 调试器中,唯一的方法是每次都键入更长的命令。当这与刚刚键入回车键会重复你发出的最后一个命令的功能结合使用时,它变得非常方便。只需为你想要查看的列表中的每个元素键入回车键即可。
调试器中还有一些可以显式设置的变量,数量不限。 你用美元符号后跟一个名称,这就是一个变量。你可以将任何 C 数据类型的值赋给这些变量,然后你可以在稍后检查它们。 这些变量的用途包括: 如果你要检查某个特定值,并且知道你将经常引用它,那么与其记住它在历史记录中的编号,不如给它一个名称。 你还可以在设置条件断点时使用它们。条件断点是许多符号调试器中的一个功能,你可以说“当程序到达这一点时停止,但前提是某个表达式为真”。调试器中的变量允许你将程序中的变量与你保存在调试器变量中的该变量的先前值进行比较。 它们的另一个用途是计数,因为毕竟,赋值在 C 中是表达式,因此你可以执行 $foo+=5
将 $foo
的值增加 5,或者直接执行 $foo++
。你甚至可以在条件断点中执行此操作,这是一种使其在第十次命中断点时中断的廉价方法,你可以执行 $foo--==0
。 大家都明白了吗? 将 foo 递减,如果现在为零,则中断。然后,你将 $foo
设置为你希望跳过的次数,然后让它继续执行。你也可以使用它来检查数组的元素。 假设你有一个指针数组,那么你可以这样做
PRINT X[$foo++]
但首先你要这样做
SET $foo=0
好的,当你这样做[指向 PRINT
表达式]时,你会得到 X 的第零个元素,然后你再次执行它,它会得到第一个元素,假设这些是指向结构的指针,那么你可能会在那里放一个星号[在 PRINT 表达式中的 X 之前],每次都会打印数组元素指向的下一个结构。 当然,你可以通过键入回车键来重复此命令。 如果单个重复操作不够用,你可以创建一个用户自定义命令。 你可以输入 Define Mumble
,然后给出一些命令,然后输入 end
。 现在就定义了一个 Mumble
命令,它将执行这些行。 将这些定义放在命令文件中非常有用。 你可以在每个目录中有一个命令文件,当你以此作为你的工作目录启动调试器时,该文件将自动加载。 因此,对于每个程序,你可以定义一组用户自定义命令,以便以有用的方式访问该程序的数据结构。 你甚至可以为你的用户自定义命令提供文档,以便它们像内置命令一样被 help
功能处理。
这个调试器中另一个不寻常的功能是能够从堆栈中丢弃帧。 因为我认为,不仅能够检查正在调试的程序中发生的事情很重要,而且能够以任何可能的方式更改它也很重要。 因此,在你发现一个问题并知道问题所在后,你可以修复这些问题,就像该代码是正确的一样,并找到下一个错误,而无需先重新编译程序。 这意味着不仅能够灵活地更改程序中的数据区域,而且能够更改控制流。 在此调试器中,你可以通过输入以下内容非常直接地更改控制流
SET $PC=<some number>
所以你可以设置程序计数器。 你还可以设置堆栈指针,或者你可以说
SET $SP+=<something>
如果你想将堆栈指针增加一定量。 但此外,你还可以告诉它从程序的特定行开始,你可以将程序计数器设置为特定的源代码行。 但是,如果你发现你错误地调用了一个函数,而你实际上根本不想调用该函数怎么办? 假设该函数非常糟糕,你真正想做的是退出该函数,并手动执行该函数应该执行的操作。 为此,你可以使用 RETURN
命令。 你选择一个堆栈帧,然后输入 RETURN
,它会导致该堆栈帧及其中的所有帧被丢弃,就像该函数现在返回一样,你还可以指定它应该返回的值。 这不会继续执行; 它会假装返回已经发生,然后再次停止程序,因此你可以继续更改其他内容。
将所有这些东西放在一起,你就可以很好地控制程序中发生的事情了。
此外,还有一个稍微有趣的事情: C 有字符串常量,如果你在调试器中计算的表达式中使用字符串常量会发生什么? 它必须在你正在调试的程序中创建一个字符串。 嗯,它确实会这样做。 它在该调试程序中设置一个对 MALLOC 的调用,让 MALLOC 运行,然后重新获得控制权。 因此,它会隐式地找到放置字符串常量的位置。
最终,当这个调试器在真正的 GNU 系统上运行时,我打算在调试器中加入一些工具来检查其下运行的进程的所有内部状态。 例如,检查内存映射的状态,哪些页存在,哪些是可读的,哪些是可写的,以及检查下级程序的终端状态。 已经有一个命令了; 与 Unix 上的调试器不同,此调试器将调试器和正在调试的程序的终端状态完全分开,因此它可以与以原始模式运行的程序一起使用,它可以与执行中断驱动输入的程序一起使用,并且还有一个命令可以让你了解有关正在调试的程序实际使用的终端设置的一些信息。 我认为,一般来说,调试器应该允许你找出下级进程中发生的一切情况。
GNU 系统还有两个主要部分已经存在。 一个是新的 C 编译器,另一个是 TRIX 内核。
新的 C 编译器是我自去年春天以来今年编写的。 我最终决定必须扔掉 PASTEL。 这个 C 编译器使用了一些从 PASTEL 中借鉴的想法,以及一些从亚利桑那大学的可移植优化器中借鉴的想法。 他们有趣的观点是通过生成简单的指令来处理许多不同类型的机器,然后在目标机器允许的情况下将多个简单指令组合成一个复杂的指令。 为了统一地执行此操作,他们使用代数表示法表示指令。 例如,ADD 指令可以这样表示
r[3]=r[2]+4
这将是他们编译器内部的表示,用于指示获取寄存器二的内容,加上四,并将其存储在寄存器三中。 以这种方式,你可以表示任何机器的任何可能的指令。 因此,他们实际上以这种方式表示了所有指令,然后当需要尝试组合它们时,他们会将一个表达式代入另一个表达式中,为组合指令生成更复杂的代数表达式。
有时,根据第一条指令的结果是否还有其他用途,可能需要使用两个赋值运算符创建组合指令。 一个用于此值 [指向 ???],另一个用于此值 [指向 ???],其中代入了第二条指令中的内容。 但是,如果这个值仅使用了一次,你可以在代入它之后将其删除; 不再需要计算它了。 因此,正确地进行替换,检查中间指令是否不更改这些值和其他此类事情实际上有点复杂。 当你支持自动递增和自动递减寻址(我现在这样做)时,你还必须对这些寻址执行各种检查,以检查你所做的事情在哪些情况下不保留值。
但是在检查完所有这些内容之后,你需要将代入的组合表达式通过模式匹配器,该模式匹配器可以识别你选择的目标机器的所有有效指令。 如果它被识别,那么你将这两个指令替换为组合指令,否则你将其保留原样。 他们的技术是通过这种方式组合两个或三个通过数据流相关的指令。
在亚利桑那编译器中,他们实际上将事物表示为这样的文本字符串,而且他们的编译器速度非常慢。 首先,我有一些想法只是使用他们的编译器并对其进行更改,但是我很清楚我必须完全重写它才能获得我想要的速度,因此我已经重写了它,以便对所有这些表达式使用列表结构表示。 像这样
(set (reg 2)
(+ (reg 2)
(int 4)))
这看起来像 Lisp,但这些的语义与 LISP 不完全相同,因为这里的每个符号都是一个特殊识别的符号。 这里有一组特定的固定符号,定义了所有你需要的符号。 每个符号都有一个特定的参数类型模式,例如:reg
总是有一个整数,因为寄存器是有编号的,但是 +
接受两个子表达式,等等。 并且每个表达式还有一个数据类型,该数据类型基本上说明它是固定的还是浮动的以及它有多少字节长。 如果需要,也可以对其进行扩展以处理其他内容。
我执行自动寄存器分配的方式是,当我最初生成此代码时,以及当我执行组合和所有这些操作时,对于每个可以放入寄存器的变量,我都会分配一个所谓的伪寄存器号,该数字从 16 或任何对于你的目标机器而言太高而无法成为真实寄存器的数字开始。 因此,真正的寄存器编号为 0 到 15 或其他数字,而高于此数字的是伪寄存器。 然后,编译器的最后一部分之一包括遍历并将所有伪寄存器更改为真正的寄存器。 同样,它会创建一个冲突图,它会查看哪些伪寄存器在同一时间处于活动状态,当然它们不能进入同一个真正的寄存器,然后它会尝试将伪寄存器尽可能多地打包到真正的寄存器中,并按照它们的重要性对其进行排序。
最后,它必须针对各种问题更正代码,例如当伪寄存器不适合真正的寄存器时发生的问题,这些伪寄存器必须放置在堆栈槽中。 当这种情况发生在某些机器上时,某些指令可能会变为无效。 例如,在 68000 上,你可以将寄存器添加到内存,也可以将内存添加到寄存器,但是你不能将一个内存位置添加到另一个内存位置。 因此,如果你有一个 ADD 指令,并且你正前往 68000,并且这两个东西最终都在内存中,那么它是无效的。 因此,最后一次传递会根据需要遍历并将事物复制到寄存器和从寄存器复制出来,以纠正这些问题。
索引寄存器也可能出现问题。 如果你尝试通过某些内容进行索引,那么大多数情况下,如果索引量位于内存中,则该代码将变为无效,除非在某些机器上你可以通过间接寻址来实现。 在你对索引寄存器执行自动递增的情况下,你可能必须将该值复制到寄存器中,执行指令,然后将递增后的值复制回它实际所在的内存槽中。
这里有很多细节需要处理,我还没有完成实现所有使它真正高效所需的细节。
这个编译器目前的工作方式是:先用一个解析器将 C 代码转换成一个带有 C 数据类型信息的语法树。然后另一个过程查看该语法树,并生成类似这样的代码 [类似 LISP 的代码]。接着是几个优化过程。一个用于处理诸如跨跳转、跳转到跳转、跳转到.+1
之类的情况,所有这些都可以立即简化。然后是公共子表达式识别器,然后是查找基本块,并执行数据流分析,以便它可以知道每个指令中使用了哪些值,以及之后不再使用。并且还将每个指令链接到它所使用的值生成的位置,所以如果我有一个指令生成伪寄存器 R[28],然后稍后有另一个指令使用 R[28],并且这是第一个使用 R[28] 的地方,我让第二个指令指回第一个指令,并且此指针用于控制尝试组合指令。你不会组合相邻的指令,而是将使用值的指令与生成该值的指令组合在一起。即使中间有其他指令,这也没有关系,你只需要检查它们是否会造成干扰。然后,在组合器之后是动态寄存器分配器,最后是将其转换为汇编代码的东西。
在亚利桑那编译器中,指令识别器是用 LEX 生成的。你的机器描述只是一个 LEX 程序,LEX 会将该程序转换为 C 函数,以将有效指令识别为字符串。而我所拥有的是一个特殊的决策树,该决策树是从以这种语法编写的机器描述生成的,就好像它是 LISP 一样。并且此识别器用作编译器的许多不同部分的子例程。
目前,这个编译器的运行速度与 PCC 大致相同。如果你告诉它不要进行复杂的寄存器分配,它的运行速度会明显加快,在这种情况下,它会像 PCC 一样分配寄存器。在它的超级复杂模式下,它在分配寄存器方面比 PCC 做得更好,并且我观察到,对于 VAX,它生成的代码是我在 VAX 上见过的任何 C 编译器中最好的。
对于 68000 来说,代码仍然不是理想的。我可以看到早期阶段有些地方做得不是最好,因为它不能完全向前看。它在早期阶段有一个选择,它会做它认为最好的事情,但实际上如果它做了另一个,后来的阶段实际上足够聪明,可以做得更好。但是早期阶段不知道后期阶段会做什么,所以我需要在其中一些事情上做更多的工作。
有时这会导致它不必要地释放寄存器。因为当数据最终进入内存并且需要将它们复制到寄存器中时,它需要获取寄存器来复制它们。这意味着占用它已经分配的寄存器,并将这些临时量踢到堆栈槽中。当然,这可能会使更多的指令失效,因为这些数据现在在内存中,而不是在寄存器中,因此它必须反复检查。有时它认为必须将数据复制到寄存器中,但实际上不必,因此它可能会释放太多东西,从而无法使用它可能使用的所有寄存器。
[问题:你有 32000 的代码生成器吗?] 还没有,但再说一次,它不是代码生成器,它只是你需要的机器描述。以这种 [类似 LISP 的] 形式描述的所有机器指令的列表。因此,实际上,除了实现关于哪些参数可以在寄存器中以及哪些类型的寄存器中存在的约束的想法的工作之外,这对于 68000 是必需的,而对于 VAX 则不需要,将此编译器从 VAX 移植到 68000 只需几天时间。所以它很容易移植。
该编译器目前生成汇编代码,并且可以生成 DBX 想要的格式的调试信息,或者 GDB 的特殊内部格式的调试信息。我想说这个编译器唯一需要做的工作是在三个方面。一:我必须添加一个“性能分析”功能,就像 Unix 编译器拥有的那样。二:我必须让这些寄存器分配器变得更智能,这样我就不会再看到输出中出现愚蠢的东西。三:还有各种各样的错误,一些它尚未正确处理的事情,尽管它已经正确地编译了自身。我预计这只需要几个月的时间,然后我就会发布该编译器。
该系统存在的另一个相当大的部分是内核。 [问题:一个停顿?] 啊,是的,我想我们忘记了中断。为什么我不先完成关于内核的讨论,这只需要大约五分钟,然后我们可以休息一下。
现在,对于内核,我计划使用一个名为 TRIX 的系统(我不知道它代表什么),该系统是作为麻省理工学院的一个研究项目开发的。该系统基于远程过程调用。因此程序被称为域。每个域都是一个地址空间和各种功能,而功能只不过是调用域的能力。任何域都可以创建“能力端口”来调用它,然后它可以将这些端口传递给其他域,并且调用系统和调用另一个用户域之间没有区别。事实上,你无法分辨你拥有的是哪一个。因此,通过其他用户程序来实现设备非常容易。文件系统可以由用户程序透明地实现。跨网络通信也是透明的。你认为你是在直接调用另一个域,但实际上你是在调用网络服务器域。它获取你在调用中给出的信息,并通过网络将其传递给另一个服务器程序,然后该程序调用你试图与之通信的域。但是你和另一个域都认为这是不可见的。
TRIX 内核正在运行,它具有一定的 Unix 兼容性,但还需要更多。目前,它的文件系统在磁盘上使用与旧的 Unix 文件系统相同的结构。这使得调试变得更容易,因为他们可以使用 Unix 设置文件,然后他们可以运行 TRIX,但是该文件系统不具有我认为必要的任何功能。
我认为必须添加的功能包括:版本号、取消删除、关于文件何时、如何以及在何处备份到磁带的信息、文件的原子替换。我认为在 Unix 中,当正在写入文件时,你已经可以看到写入的内容,例如,你可以使用 tail
来查看内容的写入程度,这非常好。并且如果程序崩溃,部分写入了文件,你可以看到它生成的内容。这些都很好,但是,部分写入的输出绝不应被视为你最终期望拥有的完整输出。该文件的先前版本应继续对所有尝试使用它的人可见和使用,直到新版本完全正确地制作完成。这意味着新版本应该在文件系统中可见,但不能以它应该具有的名称显示。它应该在完成后重命名。顺便说一句,这在 ITS 中是发生的情况,尽管在那里每个用户程序都必须显式地执行此操作。为了与用户程序的 Unix 兼容性,它必须以不可见的方式发生。
我有一个奇怪的复杂方案,试图使版本号与现有的 Unix 用户程序相匹配。这就是说,如果你只是以普通方式指定名称,则指定文件名时保留版本号的隐式性。但是,如果你希望精确地指定名称,要么是因为你想明确说明要使用哪个版本,要么是因为你根本不想要版本,则在末尾放置一个点。因此,如果你给定的文件名为 FOO
,则表示“搜索 FOO 的现有版本并获取最新的版本。” 但如果你说 FOO.
,则表示“完全使用名称 FOO,而不是其他名称。” 如果你说 FOO.3.
,则表示“完全使用名称 FOO.3”,当然它是 FOO 的第三个版本,而不是其他版本。在输出时,如果你只是说 FOO
,它最终会创建 FOO 的新版本,但如果你说 FOO.
,它将写入一个名为 FOO 的文件。
现在,在弄清楚所有细节并查看是否存在任何遗留问题,例如某些 Unix 软件是否会崩溃(尽管向它们提供带有点的名称以使其获得相同的行为)等方面,存在一些挑战。
我希望当你打开一个用于输出的文件,其名称以点结尾时,你应该立即打开该名称,这样你就可以获得相同的 Unix 行为,部分写入的输出会立即可见,而当你输出一个不以点结尾的名称时,新版本应该在你关闭它时出现,并且只有在你显式关闭它时才会出现。如果它因作业崩溃或系统崩溃等原因而关闭,则它应该使用不同的名称。
这个想法可以通过说一个不以点结尾的名称与所有没有版本号的名称匹配来连接到“星号匹配”,所以如果某个目录有这样的文件
foo.1 foo.2 bar.8
如果我说 *
,这等效于
foo bar
因为它获取所有名称并删除它们的版本,并获取所有不同的名称。但是如果我说 *.
,则它获取所有确切的名称,在每个名称后放置一个点,并与它们匹配。因此,这给了我所有存在的各个版本的所有名称。类似地,你可以看到 *.c
和 *.c.
之间的区别,[第一个] 将给你所有 .c
文件的基本上没有版本的引用,而 [第二个] 将给你所有版本… 好吧,实际上不会,你必须说 *.c.*.
;我还没有弄清楚这里的细节。
另一件事,不是用户可见的功能,并且肯定可以兼容地放入,是文件系统中的故障安全。也就是说,通过以正确的顺序将所有信息写入磁盘,安排你可以随时按下“halt”而不会因此破坏磁盘上的文件系统。这样做的方式是如此众所周知,我无法想象为什么有人会忽略它。另一个想法是进一步的冗余信息。我不确定我是否会这样做,但我有一些关于如何在每个文件中存储其所有名称的想法,从而使得如果磁盘上的任何目录丢失,都可以从磁盘的其余内容中重建它。
我还认为我知道如何使原子地更新文件的任何部分成为可能。因此,如果你想以一种任何读取文件的尝试都将仅看到旧数据或仅看到新数据的方式,用新数据替换文件的某个子范围。我相信我可以做到这一点,甚至不需要任何锁定。
对于网络支持,我打算最终为该系统实现 TCP/IP。我也认为可以使用 KERMIT 来获得与 UUCP 有效等效的东西。
我相信已经编写了一个 shell。它有两种模式,一种模仿 BOURNE shell,另一种在同一个程序中模仿 C-shell。我还没有收到它的副本,我也不知道我需要在上面做多少工作。还有许多其他实用程序存在。存在一个 MAKE,LS,正在分发一个名为 BISON 的 YACC 替代品。存在一个非常接近 LEX 的东西,但它不是完全兼容的,它需要一些工作。并且,总的来说,剩下的工作比已经完成的工作少得多,但我们仍然需要很多人来帮助。
人们总是问我“什么时候能完成?” 当然我不知道什么时候能完成,但问我这个问题是错误的。如果你打算为它付费,你当然会想知道你到底会得到什么以及何时得到。但既然你不会为它付费,你应该问的正确问题是“你如何能帮助它更快完成?” 我有一份项目清单,它在麻省理工学院的一个文件中,有兴趣帮忙的人可以发邮件到这个互联网地址,我会发回一份项目清单。(我想知道这行不行(看着黑板)。)这个能看懂吗?这是“[email protected]”(只要跟着弹跳的球。)现在让我们休息一下,休息之后,我会说一些非常有争议的事情。所以现在不要离开。如果你现在离开,你将错过真正的体验。
[这里我们休息了 15 分钟]
有人要求我宣布如何获取 GNU 软件的副本。当然,一种方法是如果你认识有副本的朋友,你可以复制它,但如果你不认识有副本的朋友,并且你没有连接到互联网,你无法通过 FTP 获取,那么你总是可以订购一份发行磁带,并向自由软件基金会捐一些钱。当然,自由程序和自由分发不是一回事。我稍后会详细解释这一点。
这里我有一本 EMACS 手册,是精美印刷的版本。它是经过照相排版然后胶印的。虽然你也可以从 EMACS 发行版中包含的源代码中自行打印,但你可以从自由软件基金会获得这些副本。你可以稍后过来看看这个,这里面也包含一张订单,你可以从中复制一些信息,而且这张[正面]图片有时也深受喜爱。这个[指着一个被 RMS 骑着 GNU 追赶的人物]是一个害怕软件囤积者,我一会儿会谈到他。
软件是一个相对较新的现象。人们大约在三十年前开始分发软件。直到大约二十年前,才有人想到以此为业。这个领域没有任何关于人们如何做事或任何人拥有什么权利的传统。对于可以从哪些其他生活领域借鉴传统,有几种想法,可以类比。
欧洲的许多教授喜欢的一种类比是程序和数学之间的类比。程序有点像一个很大的公式。现在,传统上没有人可以拥有数学公式。任何人都可以复制和使用它们。
对普通人最有意义的类比是食谱。如果你仔细想想,在日常生活中,最像程序的东西就是食谱,它是关于如何做某事的说明。不同之处在于食谱是由人而不是机器自动执行的。确实,食谱的源代码和目标代码之间没有区别,但它仍然是最接近的东西。而且没有人被允许拥有食谱。
但是,选择的类比是与书籍的类比,书籍有版权。为什么做出这样的选择?因为从做出这个特定选择中获益最多的人被允许做出决定。编写程序的人,而不是使用程序的人,被允许做出决定,他们以完全自私的方式做出了决定,结果,他们把编程领域变成了一个丑陋的领域。
当我进入这个领域时,当我在 1971 年开始在麻省理工学院工作时,我们开发的程序可能不会被共享的想法甚至没有被讨论。斯坦福大学和卡内基梅隆大学以及每个人,甚至 Digital 也是如此。当时 Digital 的操作系统是免费的。我时不时地从 Digital 系统中获得程序片段,例如 PDP-11 交叉汇编器,我将其移植到 ITS 上运行,并添加了许多功能。那个程序没有版权。
直到七十年代末,这种情况才开始改变。我对我们拥有的分享精神印象非常深刻。我们正在做一些我们希望有用的事情,如果人们可以使用它,我们很高兴。因此,当我开发第一个 EMACS 时,当人们想要在麻省理工学院以外的地方开始使用它时,我说它属于 EMACS “公社”,为了使用 EMACS,你必须成为公社的成员,这意味着你有责任贡献你所做的所有改进。对原始 EMACS 的所有改进都必须发回给我,以便我可以将它们合并到 EMACS 的更新版本中,以便社区中的每个人都可以从中受益。
但是当 SCRIBE 在卡内基梅隆大学开发,然后被卖给一家公司时,这种情况开始被破坏。这让许多大学的我们感到非常不安,因为我们看到这是一种摆在每个人面前的诱惑,不合作会如此有利可图,而我们这些仍然相信合作的人没有武器来试图迫使人们与我们合作。显然,人们会一个接一个地叛变并停止与社会其他部分合作,直到只有那些良心非常坚定的人才会继续合作。而这正是发生的事情。
编程领域现在已经变成了一个丑陋的领域,每个人都愤世嫉俗地思考着通过不善待这个领域的其他人以及用户,他会得到多少钱。
我想确定拥有软件的做法既在物质上是浪费的,在精神上对社会有害,而且是邪恶的。所有这三件事都是相互关联的。它在精神上是有害的,因为它让每一个接触到计算机的社会成员都参与到一种明显对其他人造成物质浪费的行为中。每次你为了自己的利益而做一些你明知道会伤害其他人,而且伤害远大于对你的帮助的事情时,你都必须变得愤世嫉俗,才能在你的脑海中支持这样的事情。它是邪恶的,因为它故意浪费社会所做的工作并导致社会衰败。
首先我想解释一下试图拥有软件和其他通常有用的信息造成的各种危害,然后我将反驳为支持这种做法提出的论点,然后我想谈谈如何对抗这种现象,以及我是如何对抗它的。
拥有信息的想法在三个不同的层面上是有害的。在三个不同的层面上造成物质损害,并且每一种物质损害都有相应的精神损害。
第一个层面是它会阻止程序的使用,导致更少的人使用程序,但实际上,为更少的人使用程序,工作量并不会减少。当你在使用程序时有一个价格时,这是一种激励,这是那些软件囤积者喜欢使用的词,价格是一种激励,激励人们不使用程序,这是一种浪费。例如,如果因为程序有价格,只有一半的人使用它,那么这个程序就被浪费了一半。同样的工作量只产生了原来一半的财富。
事实上,你不需要做任何特别的事情就可以让一个程序传到所有想要使用它的人手中,因为他们自己完全可以复制它,而且它会传给每个人。在你编写完程序后,你所要做的就是坐下来,让人们做他们想做的事情。但事实并非如此;相反,有人故意试图阻碍程序的共享,事实上,他不仅仅试图阻碍它,他还试图向其他人施加压力,让他们来帮忙。每当一个用户签署保密协议时,他基本上就出卖了他的其他用户。他没有遵循黄金法则,说“我喜欢这个程序,我的邻居也会喜欢这个程序,我希望我们两个都有它”,而是说“是的,给我吧。管他的邻居!我会帮你把它瞒着我的邻居,给我吧!”这种精神就是造成精神伤害的原因。这种态度是说,“管他的邻居,给我一份。”
在我遇到一些人说他们不让我复制某些东西,因为他们签署了一些保密协议之后,当有人要求我签署类似的东西时,我就知道这是错误的。我不能对别人做我被别人做时让我如此生气的事情。
但这仅仅是其中一个危害层面。当人们想要更改程序时,就会出现第二个危害层面,因为没有哪个程序真的适合所有想要使用它的人。就像人们喜欢改变食谱一样,比如少放点盐,或者他们可能喜欢加一些青椒,所以人们也需要更改程序才能获得他们需要的效果。
现在,软件所有者并不真正在乎人们是否可以更改程序,但阻止人们更改对他们有利。通常,当软件是专有的时,你就无法获得源代码,你无法更改它,这会导致程序员浪费大量工作,并导致用户产生大量挫败感。例如:我有一个朋友告诉我,她在一家银行工作了几个月,她是一名程序员,编写一个新的程序。现在,有一个市售的程序几乎是对的,但它就是不太符合他们需要的东西,事实上,它对他们来说毫无用处。要使它能够满足他们的需求可能只需少量更改,但由于该程序的源代码不可用,因此这是不可能的。她不得不从头开始,浪费了大量的工作。我们只能推测世界上有多少程序员在以这种方式浪费他们的时间。
还有一种情况是,程序虽然足够用,但用起来不舒服。举个例子:我们在麻省理工学院第一次拥有图形打印机时,我们自己编写了软件,并添加了许多不错的功能,例如,当你的打印作业完成后,它会给你发送消息;如果打印机没纸了,而你的队列里还有打印作业,它也会给你发送消息。还有许多其他我们想要的功能。后来,我们得到了一台好得多的图形打印机,最早的激光打印机之一,但它的软件是由施乐公司提供的,我们无法更改它。他们不肯添加这些功能,我们也做不到,所以我们不得不凑合使用那些“半吊子”的东西。知道我们已经准备好,并且有能力修复它,但却被禁止这样做,这令人非常沮丧。我们被破坏了。
还有很多人使用电脑,却说电脑对他们来说是个谜,他们不知道电脑是如何工作的。他们怎么可能知道呢?他们无法阅读他们正在使用的程序。人们了解程序应该如何编写,或者程序如何工作,唯一的方法是阅读源代码。
所以,我不禁怀疑,用户只是把计算机当成工具的想法,实际上是不是一种自我实现的预言,是由于源代码保密的做法导致的。
现在,与这种物质损害相关的精神损害,体现在自给自足的精神上。当一个人花大量时间使用计算机系统时,该计算机系统的配置就成了他居住的城市。正如我们房屋和家具的布置方式决定了我们生活其中的感受一样,我们使用的计算机系统也是如此。如果我们无法更改我们使用的计算机系统来适应我们,那么我们的生活实际上就受他人控制。看到这一点的人会在某种程度上感到沮丧:“试图改变这些东西是没用的,它们总是会很糟糕。甚至没必要费心去弄。我只要打发时间……等结束了,我会离开,尽量不去想它。”这种精神,这种缺乏热情的状态,就是当你有公共精神却不被允许让事情变得更好时所导致的。
第三层损害是软件开发人员之间的互动。因为任何知识领域的进步都最依赖于人们在前人的工作基础上进行构建,但对信息的所有权却明确旨在阻止其他人这样做。如果人们可以在别人的工作基础上进行构建,那么所有权就会变得不明确,所以他们确保每个进入该领域的新手都必须从头开始,从而大大减缓了该领域的进步。
我们可以看到:有多少电子表格系统是由不同的公司制造的,却没有借鉴任何之前是如何完成的理解?是的,没错,第一个编写的电子表格并不完美。它可能只在某些类型的计算机上运行,并且在某些方面的处理方式并非最佳。因此,有些人会有各种理由想要重写它的部分内容。但是,如果他们只需要重写他们真正想要改进的部分,那么工作量就会少很多。你可能知道如何改进系统的某个方面,但你可能不知道如何改进同一系统的另一个方面,事实上,你可能很难做得更好。现在,如果你可以只采用你喜欢的部分,并只重做你受到启发的部分,那么你就可以拥有一个在各个方面都更好的系统,而所需的工作量比现在编写一个全新的系统要少得多。我们都知道,一个系统通常可以通过完全重写来获益,但这只有在你能够先阅读旧系统的情况下才行。
因此,编程领域的人们已经进化出一种浪费大量时间的方式,从而人为地制造了对程序员的需求,实际上我们并不需要那么多程序员。为什么会出现程序员短缺?因为有了知识产权,程序员们已经安排浪费了他们所做工作的一半,所以我们似乎需要两倍的程序员。因此,当人们指出知识产权制度并说“看看大量的就业统计数据,看看这个行业有多大”时,真正证明的是人们正在浪费大量的金钱和时间。如果他们谈论寻找提高程序员生产力的方法,如果涉及更高级的工具,他们很乐意这样做,但要通过消除那些明确用来降低程序员生产力的做法来提高程序员生产力,他们就会反对。因为这会减少雇佣的程序员数量。这里面有点精神分裂。
与这种物质损害相对应的精神损害,是对科学合作精神的损害。这种精神曾经非常强烈,以至于即使在交战的国家,科学家也会继续合作,因为他们知道他们所做的事情与战争无关,只是为了人类的长期利益。现在,人们不再关心人类的长期利益了。
为了了解阻碍程序使用是什么感觉,让我们想象一下,我们有一个三明治,你可以吃它,而且它不会被消耗掉。你可以吃它,另一个人可以吃它,同一个三明治,无论多少次,它都会像最初一样营养丰富。
最好的做法,我们应该对这个三明治做的事情是把它带到有饥饿的人的地方;尽可能多地带给更多人,以便尽可能多地喂饱人们。无论如何,我们不应该为吃这个三明治定价,因为那样人们就买不起,它就会被浪费掉。
程序就像这个三明治,但更甚,因为它可以在多个不同的地方同时被食用,被不同的人依次使用。就好像这个三明治足以永远喂饱所有地方的所有人,但却不允许发生,因为有人认为他应该拥有它。
现在,那些认为他们可以拥有程序的人,通常会提出两种论点。第一个是“我写的,它是我的精神、我的内心、我的灵魂的孩子。怎么能有人把它从我身边夺走呢?无论它去哪里,它都是我的,我的,我的!!” 奇怪的是,他们中的大多数人都会签署协议,声明它属于他们工作的公司。
所以我认为,这是你可以很容易地说服自己相信很重要的事情之一,但你也同样可以很容易地说服自己它根本不重要。
通常,这些人会使用这个论点来要求控制人们如何更改程序的权利。他们说:“任何人都不能搞砸我的艺术品。” 想象一下,发明一道菜的人有权控制你如何烹饪它,因为它他的艺术品。你想不放盐,但他会说“哦,不。我设计的这道菜,必须放这么多盐!” “但是我的医生说我吃盐不安全。我该怎么办?”
显然,正在使用程序的人更接近事件本身。程序的使用直接影响到他,而它与编写程序的人只有一种抽象的关系。因此,为了尽可能地让人们控制自己的生活,必须由用户来决定这些事情。
他们提出的第二个论点是经济上的。“人们如何获得报酬来编程?”他们说,这里面确实有一些实际问题。但他们说的很多都是困惑。困惑之处在于,说“如果我们想让很多人编程,我们必须安排他们不需要以其他方式谋生”和说“我们需要有当前的系统,你需要通过编程来发财”完全不同。仅仅维持生计和赚取程序员(至少在美国)现在所赚的那种钱之间存在很大差异。他们总是说:“我怎么吃饭?”但真正的问题不是“他会吃什么?”而是“他怎么吃寿司?”“我怎么能有房顶遮头?”但真正的问题是“他怎么买得起公寓?”
当前的系统是由那些投资于软件开发的人选择的,因为它让他们有可能赚到尽可能多的钱,而不是因为这是唯一一种可以为系统开发工作提供资金的方式。事实上,即使在最近的十年或十五年前,也常用其他方式来支持软件开发。例如,那些免费的数字操作系统,即使在 70 年代早期,也是由那些为此工作而获得报酬的人开发的。许多有用的程序是在大学开发的。现在,这些程序通常被出售,但在十五年前,它们通常是免费的,但人们仍然为此工作而获得报酬。
当你有像程序这样的东西,像一个无限的三明治,像一条道路,它必须被建造一次,但一旦建成,无论你使用它多少次都无关紧要,使用它没有成本,通常如果我们不对其使用定价会更好。我们现在开发了很多这样的东西,并付钱给人们去建造。例如,外面的所有街道。很容易找到愿意无偿编程的人;找到愿意无偿建造街道的人真的不可能。建造街道不像编程那样具有创造性和乐趣。但是我们有很多街道,我们确实有资金来支付他们,我们这样做的方式比我们说:“让公司去建造街道,并设立收费站,然后每次你转过另一个街角,你都要支付另一笔费用。然后那些选择在好地方建造街道的公司就会盈利,而其他公司则会破产。”
每当有人想出一种通过囤积某种东西来赚大钱的方法时,就会发生一件有趣的事情。在那之前,你可能会看到很多人对那个领域充满热情,渴望在那里工作,他们唯一的问题是如何才能获得任何生计。例如,如果我们想到数学家,就会发现想成为纯粹数学家的人比任何支持他们成为纯粹数学家的资金都要多得多。即使你得到了资助,你也得不到很多,他们的生活并不富裕。对于音乐家来说,情况更糟。我看到一个关于马萨诸塞州普通音乐家,即大部分时间都投入到音乐事业中的人的平均收入的统计数据,大约是中位数收入的一半甚至更少。这 barely 足够维持生活,非常困难。但是有很多人在尝试这样做。然而,不知何故,当普遍有可能通过做某事获得高薪时,所有这些人都会消失,人们开始说“除非得到那么高的报酬,否则没人会做这件事。”
我在编程领域也看到了这种情况。曾经在人工智能实验室工作,薪水很少却乐在其中的人,现在做梦都不会想到以低于年薪五万美元的价格工作。发生了什么?当你在人们面前展示赚大钱的可能性,当他们看到其他做类似工作的人获得了那么多钱时,他们会觉得他们也应该得到同样的报酬,因此没有人愿意继续以前的做法。在这种事情发生后,很容易认为付给人们很多钱是唯一的方法,但事实并非如此。如果不存在赚大钱的可能性,就会有人愿意接受以少量的钱来做这件事,特别是当这件事具有创造性和乐趣时。
现在我看到人工智能实验室的独特世界被摧毁了,我看到销售软件是摧毁它的固有因素,而且正如我之前解释的那样,你需要有自由软件才能拥有那样的社区。但是,经过更深入的思考,我意识到囤积软件在各个方面都会损害整个社会,特别是通过迫使人们出卖邻居并导致社会衰败。这与人们在街上看到有人被刺伤却不告诉任何人的精神一样。我们可以在周围的许多公司里看到这种精神。我很清楚我有一个选择,我可以成为那个世界的一部分,并对我自己正在做的事情感到不快乐,或者我可以决定与它作斗争。所以我决定战斗。我毕生的职业生涯都致力于重建软件共享社区,试图结束囤积一般有用信息的现象。GNU系统是实现这一目标的手段。它是一种技术手段,旨在达到社会目的。我希望通过GNU系统,让用户能够抵御软件囤积者的威胁。
现在,囤积者基本上声称拥有使个人电脑变得无用的权力。大约五十年前,在美国有一些人,最常见的是黑手党,他们会去商店和酒吧,特别是当酒吧还是非法的时候。他们会上前说:“最近很多地方都着火了。你肯定不希望你的地方着火吧?我们可以保护你免受火灾,你只需要每月付给我们一千美元,我们就会确保你这里不会发生火灾。”这被称为“保护费勒索”。现在,我们遇到这样一种情况,有人说:“你有一台不错的电脑,你正在使用一些程序。如果你不希望这些程序消失,如果你不希望警察来找你,你最好付给我一千美元,我会给你一份带有许可的程序副本,”这被称为“软件保护费勒索”。
实际上,他们所做的只是干扰其他人做需要做的事情,但他们是在假装,不管是他们自己还是我们其他人,他们都在提供有用的功能。我希望当那个软件黑手党的人走过来问:“你想让你的电脑上的那些程序消失吗?”时,用户可以说:“我再也不怕你了。我有这个免费的GNU软件,你现在对我无能为力了。”
现在,人们有时为拥有软件提供的理由之一是给人们提供生产东西的激励。我总体上支持私营企业的理念,以及希望通过生产其他人喜欢使用的东西来赚钱的想法,但它现在在软件领域已经失控了。生产专有程序与生产相同的程序并使其免费对社会的贡献不同。因为编写程序只是对社会的一种潜在贡献。只有当程序被使用时,才会真正对社会财富做出贡献。如果你阻止程序被使用,那么这种贡献实际上就不会发生。因此,社会需要的不是每个人都如此有动力去制作的这些专有程序,我们真正想要的是自由软件,因此我们的社会正在失控,因为它鼓励人们去做没有用的事情,而没有鼓励人们去做有用的事情。因此,私营企业的基本理念没有得到遵循,你甚至可以说这个社会是神经质的。毕竟,当一个人鼓励他人做出对自己不利的行为时,我们称之为神经症。这里,社会正以这种方式行事,鼓励程序员做对社会不利的事情。
我与众不同。我宁愿相信自己是社会的好成员,并且正在做出贡献,而不是感觉自己成功地在剥削社会,这就是我决定做我所做的事情的原因。但是,每个人至少都会为他们正在做的事情感觉有点不安,因为他们正在被支付去做实际上没有用的事情。所以,让我们停止捍卫这种鼓励做错事的激励的想法,让我们至少尝试提出一些安排来鼓励人们做正确的事情,那就是制作自由软件。
谢谢大家。
[在这之后,RMS回答了大约一个小时的问题。在这个版本中,我只收录了很少一部分问题和答案。录音效果很差,我没有时间对所有内容进行适当的整理。]
- 问: 有没有人试图给你制造麻烦?
答: 唯一一次有人试图给我制造麻烦的是那些自称拥有Gosling Emacs的人。除此之外,他们没有理由这样做,所以他们做不了什么。顺便说一下,我想请大家注意人们如何使用语言来试图鼓励人们思考某些想法,而不是思考其他想法。该领域当前使用的大部分术语是由自称拥有软件的人选择的,目的是试图鼓励你将软件视为类似于有形财产的物质对象,而忽略了它们之间的差异。最明显的例子是“盗版”这个词。请拒绝使用“盗版”一词来形容那些希望像好公民一样与邻居分享软件的人。
我忘了告诉你们:版权的概念是在印刷机发明后才出现的。在古代,作者们可以自由地互相抄袭,这并不被认为是错误的,而且甚至很有用:某些作者的作品能够流传下来,即使是片段,也是因为其中一些作品被大量引用在其他流传下来的作品中。
这是因为书籍是一次复制一份的。制作十份副本的难度是制作一份副本的十倍。然后,印刷机被发明了,这并没有阻止人们手工抄写书籍,但与印刷相比,手工抄写是如此令人不快,以至于它可能已经不可能了。
当书籍只能通过大规模生产制造时,版权开始变得有意义,它也没有剥夺阅读公众的自由。作为不拥有印刷机的公众成员,你无论如何都无法复制书籍。所以,仅仅因为有版权,你并没有失去任何自由。因此,版权被发明出来,并且由于技术变革在道德上变得有意义。现在,相反的变革正在发生。个人复制信息的能力越来越强,我们可以看到,技术的最终进步是使复制任何类型的信息成为可能。[由于磁带翻转而中断]
因此,我们又回到了古代,当时版权没有意义的情况。
如果我们考虑一下我们对财产的概念,它们来自物质对象。物质对象基本上满足守恒定律。是的,我可以把粉笔掰成两半,这不是重点,它会被磨损,它会被消耗。但基本上,这是一把椅子[指着一把椅子]。我不能只是打个响指就变出两把椅子。获得另一把椅子的唯一方法是按照第一把椅子建造的方式建造它。它需要更多的原材料,它需要更多的工作量,我们的财产观念是为了使道德观念与这些事实相符而演变出来的。
对于任何人都可复制的信息,事实是不同的。因此,与之相适应的道德态度也是不同的。我们的道德态度来自于思考做某些事情会对人们有多大的帮助,以及会伤害人们到什么程度。对于物质对象,你可以来拿走这把椅子,但你不能来复制它。如果你拿走了这把椅子,它就不会产生任何东西,所以这是没有任何借口的。如果有人说:“我做了制作这把椅子的工作,只有一个人可以拥有这把椅子,那个人最好是我,”我们可能会说:“是的,这很有道理。”当一个人说:“我在这张磁盘上雕刻了比特,只有一个人可以拥有这张磁盘,所以你别想把它从我这里拿走,”这也有道理。如果只有一个人拥有这张磁盘,那个人最好是拥有这张磁盘的人。
但是,当其他人走过来说:“我不会损坏你的磁盘,我只是会神奇地制作另一个一模一样的磁盘,然后把它拿走,这样你就可以像以前一样继续使用这个磁盘了”,这就像有人说:“我有一个神奇的椅子复制机。你可以继续享受你的椅子,坐在上面,随时都能用它,但我也会有一把椅子。”这很好。
如果人们不需要建造,他们只需要打个响指就能复制它们,那就太棒了。但是这种技术的改变不适合那些想要拥有单独副本并从单独副本中获利的人。这个想法只适用于被保护的物体。所以他们尽最大努力将程序渲染成物质对象。你有没有想过,为什么当你去软件商店购买一个程序副本时,它会装在一个看起来像书的东西里?他们希望人们认为他们得到的是物质对象,而不是意识到他们真正拥有的是可以复制的数字数据。
毕竟,计算机到底是什么?不就是一台通用机器吗?你可能研究过通用图灵机,这种机器可以模仿任何其他机器。通用机器之所以如此优秀,是因为你可以让它模仿任何其他机器,并且可以复制和更改指令,这正是你不能对物质对象做的事情。而这正是软件囤积者想要阻止公众做的事情。他们想要享受技术变革带来的好处,即通用机器,但他们不希望公众获得这种好处。
本质上,他们试图保留“物质对象时代”,但它已经过去了,我们应该使我们的是非观念与我们所生活的世界的实际情况同步。
- 问:所以归根结底是信息的所有权。你认为在某些情况下,拥有信息是正确的吗?
答:对于那些不常用的信息,或者具有个人性质的信息,我认为是可以的。换句话说,不是关于如何做事情的信息,而是关于你打算做什么的信息。对其他人来说只有投机价值的信息,也就是说他们可以从你那里拿走一些钱,但他们实际上不能用它创造任何东西。我认为,将这类事情保密和控制是完全合理的。
但是就创造性信息而言,人们可以使用或享受的信息,而且拥有的人越多就会被使用和享受得越多,我们应该始终鼓励复制。