启示录1:丑陋的、恶劣的与美好的
编辑笔记:这篇启示录已经过时,但出于历史原因仍然保留在此。有关最新信息,请参阅概要01。
目录 |
•RFC 141:这是最后一次主要修订 |
人们听到启示录这个词时会感到害怕,但在这里我是指它的好意:揭示。启示录的本意是向好人传达好消息。(如果它也向坏人传达坏消息,那也无所谓。只是不要做坏事。)
在这些专栏中,我将揭示Perl 6的设计。或者更准确地说,这个设计的起点,因为设计过程在我对此事发表初步意见之后肯定会继续。我不是全知全能的,尽管有相反的传言。扮演上帝的角色对我来说有点太大。尽管如此,总得有人来做这件事,所以我会尽力假装自己能行。我还希望你们所有人能帮助我创造历史的过程。我们都要发挥我们的自由意志,尽我们的一份力。
“如果你看看到目前为止Perl 6的历史,你就会明白为什么这个专栏的标题是《丑陋的、恶劣的与美好的》。去年的RFC过程在好意上很丑陋。这是一个头脑风暴的过程,这意味着它是故意丑陋的——不是在粗鲁无礼的意义上,因为RFC过程实际上出奇地有礼貌,而是在意义上,RFC中的建议几乎没有连贯的设计。坦率地说,RFC们漫无目的,实际上并没有覆盖到地图。存在相互矛盾的RFC,也存在缺失的RFC。许多RFC提出了真正的问题,但在提出解决方案时却偏离了奇怪的角度。其中许多只是修补症状而没有治愈根本的疾病。
Larry Wall将在今年的开源大会上发表他一年一度的娱乐性演讲,涵盖Perl 5和Perl 6的现状。不要错过这个难得的机会,听听Perl、修补和运行创造者的见解。 |
我还发现了Larry的第一条语言重设计定律:每个人都想要冒号。
这就是丑陋的部分。恶劣的部分是我本应在这两周内将这些RFC整理成一个连贯的设计。我开始认为我可以将RFC分类为好、坏、丑,但不知何故,大多数都落入了丑陋的类别,因为好的那些通常有一些问题,即使是坏的那些通常也表明了一个可能需要思考的问题,即使解决方案是完全错误的。
现在已经是五个月之后,我一直在思考这个问题,不管是什么定义的思考。你们中许多人知道当你的Perl进程大小超过你的物理内存大小时会发生什么——你会开始交换。基本上,这就是发生在我身上的事。我无法一次将足够的问题放入我的头脑中,以便取得良好的进展,而且我实际上并不擅长细分问题。我的强项是综合,而不是分析。生活中的许多分心的事情并没有帮助,其中一些是我自己造成的,还有一些不是。我不会详述这些。留到我的非官方自传中去。
《Perl编程》,第3版 |
但现在是好的一部分。(希望如此。)经过对许多个别RFC的深思熟虑,并且不知道如何整体地思考它们,我终于意识到(终于!)思考事物的正确顺序,或多或少地与《骆驼书》中的章节顺序相同。也就是说,《骆驼书》的顺序是为了最小化Perl解释中的前瞻性引用,所以以大致相同的顺序考虑Perl 6将倾向于减少我在做出决定之前需要决定的事情的数量。
所以我愉快地根据章节编号对所有RFC进行了分类,现在看起来更容易管理了。(我还重新组织了我的电子邮件,这样我就可以查看所有曾经讨论过特定RFC的消息的一部分,无论这些消息在哪个邮件列表上。这也非常有帮助。)我打算为每个章节制作一份《大灾变》,所以《大灾变》1对应于第一章:《Perl概述》。(当然,在书中,概述更像是一个小教程,而不是Perl哲学基础的完整分析。尽管如此,它是一个方便的分类点,用于分类那些在那个层面上讨论Perl 6的RFC。)
所以今天我要讨论以下RFC
RFC PSA Title
--- --- -----
16 bdb Keep default Perl free of constraints such as warnings and
strict.
26 ccb Named operators versus functions
28 acc Perl should stay Perl.
73 adb All Perl core functions should return objects
141 abr This Is The Last Major Revision
PSA评分代表“问题、解决方案、接受度”。问题和解决方案按a-f等级评分,你经常会发现我给问题评的分数高于解决方案。接受度评分是以下之一:
a Accepted wholeheartedly
b Accepted with a few "buts"
c Accepted with some major caveats
r Rejected
如果我认为某个决定为时尚早,我可能会在某个时候添加一个“d”表示延期。
RFC 141:这是最后一次重大修订
起初我倾向于接受这个RFC,但决定基于神学原因拒绝它。在启示录文学中,7是代表完美的数字,而6是代表不完美的数字。实际上,我们可能不会像RFC中建议的那样最终收敛到一个版本号2*PI
,而是收敛到6.6.6
,这将相当不幸。
所以Perl 7将是最后一次重大修订。事实上,Perl 7将如此完美,以至于根本不需要修订。Perl 6只是Perl 7的原型。:-)
实际上,我同意RFC的基本情感——我只是因为娱乐价值而拒绝它。我希望Perl能够继续演变,以更好地适应人们希望用它解决的问题。为此,我有一些设计目标,如果只是浏览RFC,这些目标可能会被掩盖。
首先,Perl将支持多种语法,这些语法映射到单个语义模型。其次,该单个语义模型将反过来映射到多个平台。
多种语法听起来像是一件坏事,但它们对于语言的演变实际上是必要的。在某种程度上,Perl 5已经有一个多语法模型;每次你使用pragma或模块时,你都在扭曲你所使用的语言。只要模块顶部的声明清楚地表明你使用的是哪种语言版本,这就会引起很少的问题。
支持多种语法的例子特别有力,它将允许持续演变,比如从Perl 5到Perl 6本身的迁移。请参阅下面的RFC 16讨论。
多种后端是我们今天生活的世界的必要性。Perl 6不能仅限于在可以用C编写的平台上运行。它必须能够在其他类型的虚拟机上运行,例如Java和C#支持的虚拟机。
RFC 28:Perl应该保持Perl。
我满怀希望,喜欢Perl 5的人会更喜欢Perl 6。话虽如此,我也希望Perl将继续努力成为所有人的选择,因为这也是Perl的一部分。
虽然我在原则上接受RFC(也就是说,我并不打算发疯),但我对它有一些重要的保留意见,因为我认为它没有必要地担心几种编程范式会“接管”设计。这不可能发生。Perl之所以是Perl,部分原因在于它故意是多范式的。你可以说,Perl允许你在不是“范式狂热者”的情况下成为范式。
Perl的本质实际上是上下文敏感性,不仅仅是语法上下文,还包括语义、实用和文化的上下文。这个整体哲学在Perl 6中不会改变,尽管具体的上下文敏感性可能会来去。目前的一些上下文敏感性实际上阻碍了我们更好地在其他领域的工作。通过故意打破一些东西,我们可以使Perl比现在更好地理解我们的意思。
作为一个具体的例子,如果我们有勇气打破@foo
和$foo[]
之间“奇特”的关系,事情可能会有所改进。诚然,我们会失去当前的切片表示法(它可以被更好的东西所取代,我相信)。但是,通过一致地对待@foo
作为一个在标量上下文中返回数组引用的表达式,我们可以使下标始终接受一个数组引用,这解决了很多问题,比如在Perl 5中要求我们区分$foo[]
和$foo->[]
。关于这一点,我们将在Apocalypse 2中做更多讨论,那时我们将剖析像RFC 9:Highlander Variable Types这样的想法。
RFC 16:保持默认的Perl不受警告和strict之类的约束。
我对这场辩论有两种想法——双方都有很好的论点。如果你阅读了这些讨论,所有的论点都被有力地提出并反复强调。具体的讨论当然集中在严格性问题上,但RFC的标题声称这是一个更普遍的哲学立场,因此它最终出现在这个Apocalypse中。
我稍后将讨论严格性和警告,我还会讨论一般的约束,但我首先想绕道一些更神秘的设计问题。在我看来,这个RFC(以及它所反对的RFC)是为什么像我这样的语言设计者必须对其进行判断的原因,因为它们都是对的,同时又是错的。许多RFC都明确地提出了立场并有力地捍卫,但未能指出可能的妥协领域。当然,RFC集中关注特定领域而不是试图做所有事情是正确的。但由于所有这些RFC都是基于(主要是)Perl 5的设计来撰写的,它们甚至无法在Perl 6的设计强制实施的地方进行综合妥协。
对我来说,一个主要的问题是是否有可能将Perl 5代码转换为Perl 6代码。一个特别的关注点是这里和那里的shell脚本中嵌入的许多单行代码。实际上没有很好的方法来翻译这些调用,因此要求设置“no strict”的新命令行开关是不可行的。
一个紧密相关的问题是Perl将如何识别它意外地被喂了Perl 5代码而不是Perl 6代码。突然给工作代码一套全新的语义将是相当糟糕的。我相信答案是,根据定义,不可能意外地喂Perl 5代码给Perl 6。也就是说,Perl 6必须假设它正在被喂Perl 5代码,直到它知道否则。这暗示我们必须有一些明确的声明来明确声明代码是Perl 6。
现在,有正确的方法和错误的方法来做这件事。我对 DEC 在将 BASIC/PLUS 升级以处理长变量名时采取的方法感到愤怒。他们的解决方案是要求所有使用长变量名的程序在顶部使用 EXTEND
命令。所以从那时起,所有的 BASIC/PLUS 程序都在顶部有 EXTEND
。我不知道是该称之为“糟糕”还是“丑陋”,但肯定不是“好”。
更好的方法是修改一些无论如何都必须存在的东西。如果你去 CPAN 看看那里的每个模块,你在顶部看到的是什么?答案:一个“package
”声明。所以我们就打破它。
我郑重声明,文件开头的“package
”声明明确表示你正在解析 Perl 5 代码。如果你想编写一个 Perl 6 模块或类,它将以“module
”或“class
”关键字开始。我还不知道模块或类声明的确切语法,但我知道的一件事是,它将设置当前的全局命名空间,就像“package
”声明做的那样。
现在,通过一次性的操作,可以通过使模块和类默认为严格,带有警告,来解决大型编程中的许多问题。但请注意,主程序(以及单行程序)的默认值是 Perl 5,这是非严格的定义。我们仍然需要弄清楚 Perl 6 主程序应该如何与 Perl 5(使用“use 6.0
”可能?)区分开来,以及 Perl 6 主程序是否应该默认为严格(我认为不应该),但你已经可以看到,一个课程教师可以威胁不及格任何没有在程序开头放置“module Main
”的人,而实际上并没有告诉他们的学生这样做是因为它打开了严格和警告。
还有其他方法,但这让我们面临一个更深层次的问题,即项目政策和站点政策的问题。人们总是渴望从各种位置自动读取各种文件,我总是坚定不移地抵制这种做法,因为它使得脚本隐式地不可移植。然而,显式的不兼容是可以接受的,所以我们的假设性课程教师可以坚持要求程序以“use Policy;
”或类似的内容开始。
但这再次表明这如何导致更深层次的语言设计问题。真正的问题是,在 Perl 5 中很难编写这样的 Policy 模块,因为它实际上不是一个模块,而是一个元模块。它想代表学生使用“use strict
”和“use warnings
”,但它无法做到。因此,我们必须在 Perl 6 中实现的一项功能是能够编写看起来像普通使用语句的元使用语句,但实际上代表用户声明其他事情,为了用户的利益,或项目的利益,或站点的利益。(随便什么。我可不是政策狂热者。)
所以,我是否同意这个 RFC 真的取决于它所说的“默认”是什么意思。就像 Humpty Dumpty 一样,我将让它意味着我认为最方便的意思。这就是上下文敏感性的作用。
我也碰巧同意这个 RFC,因为我的哲学立场是,道德在自愿选择时工作得最好,而不是在强制时。然而,有时应该强烈建议道德,我认为模块和类是这样做的好地方。
RFC 73:所有 Perl 核心函数都应该返回对象
我不确定这属于概述,但无论如何,它在这里。原则上,我同意这个 RFC。当然,如果所有 Perl 变量在底层都是对象,这个 RFC 就微不足道了。但真正的问题是,对于给定的性能级别,你可以返回一个多么有趣的对象。Perl 5 的对象相对较重,如果 Perl 6 的对象同样重,事情可能会变得缓慢。
我认为解决方案是更好的抽象类型支持,这些类型的数据值恰好由C struct
内部表示。当我们尝试将一个C struct
,比如struct tm
,转换为一个实际的哈希值时,就会陷入困境。另一方面,将struct tm
转换为另一个struct tm
效率较高,因为这是一个无操作。我们可以让这样的struct
看起来像Perl对象,并以属性方法高效地访问它,就像它是一个“真实”的对象。这种类型学(希望)将主要只带来抽象开销。最大的开销可能是struct
相对于(例如)int
的内存管理,这种开销可以通过一些上下文感知优化的大部分时间消除。
无论如何,我想指出,当我们讨论使事物返回以前未返回的对象时,没有人应该感到恐慌。请记住,任何对象都可以定义其stringify
和numify
重载来执行类喜欢做的事情,所以看起来像这样的旧代码
print scalar localtime;
可以继续运行而不改变,即使localtime
可能在标量上下文中返回一个对象。
RFC 26:命名运算符与函数
这里还有一个RFC,因为它没有更好的地方可以放置。
我发现这个RFC有些令人困惑,因为其摘要似乎暗示了比描述描述的更激进的方案。如果你忽略摘要,我基本上同意它的观点。在Perl 5中,我们已经通过它们的调用方式来区分运算符和函数,而不是它们的定义方式。RFC可以澄清的一个地方是,Perl 5区分了两类命名运算符:命名一元运算符与列表运算符。它们之所以被区分,是因为它们有不同的优先级。我们将在Apocalypse 3下讨论优先级改革,但我怀疑我们不会将这两种命名运算符结合起来。(作为一个悬念,我看到简化Perl优先级表从24级降至18级的方法,尽管在较少使用的操作中可能会对C兼容性造成一些损害。稍后会有更多关于这个话题的讨论。)
Perl 6末日预言 |
"末日预言"系列的其余部分可以在这里找到,以及Larry Wall的其他文章。 |
你开始明白为什么我被任命的工作远不止投票赞成或反对RFC吗?有许多重大问题需要面对,这些问题根本不是由RFC解决的。我们必须决定我们文化中有多少是应该被抛弃的负担,有多少是我们自己的本质。我们必须使Perl 5到Perl 6的迁移过程尽可能平滑,以防止人们以此为借口不采用Perl 6。我们必须盯着所有这些问题,直到我们看到问题的本质,以及更深层次的问题。然后在我们深入理解的过程中,我们必须保持Perl足够简单,以便任何人都可以立即开始使用它来完成工作。
敬请期待第2次末日预言,我们将尝试改变我们的变量,质疑我们的引号,重新定位我们的上下文,总之为所有后续内容设定词汇舞台。
标签
反馈
这篇文章有什么问题吗?请通过在GitHub上打开一个问题或拉取请求来帮助我们。