利奥·怀特的语言设计

2020-10-25 17:11:51

欢迎收看“信号与线索”栏目,我们将深入探讨简街的每一层技术。我是罗恩·明斯基。今天,我们将与利奥·怀特就编程语言设计展开对话。Leo在简街我们的编译器团队工作,他主要从事所谓的编译器前端的工作,这意味着他花了很多时间考虑语言功能和支持这些语言功能的类型系统,特别是,他在OCaml中做这项工作,OCaml是我们日常使用的编程语言。利奥,首先,我很好奇,你能告诉我们你是如何参与这一切的吗?首先,您是如何参与编程语言设计的?

从很小的时候起,我就对编程语言产生了一些兴趣。我在11岁左右开始编程,然后我想我对这些神秘的东西是如何创造的相当感兴趣。在这方面,我能想到的最有影响力的事情是,在我大学一到二年级的时候,我记得我读过本杰明·皮尔斯的“类型和编程语言”(Types And Programming Languages)。那真的很合拍。我只是觉得这些东西很棒,我真的很想在它上面下功夫,探索那些想法。所以,我认为这是让我投入其中的主要原因之一。我知道我想做一些编程语言的工作,我开始在那个领域攻读博士学位。它更多的是关于编译而不是编程语言设计,我在做一个源代码到源代码的C编译器,我用OCaml编写那个编译器,因为OCaml有一个很好的库来读取C文件,而且我已经了解了标准ML,因为这是他们在剑桥大学第一年教给你的。所以,不管怎样,我用OCaml来编写这个编译器,我意识到有一个我想要的语言功能可以让我更容易地编写这个C编译器,因为我有点讨厌我在C编译器上所做的工作,而且对它也不是很感兴趣,所以我推迟了,而是把这个功能添加到OCaml中。这就是我如何开始为OCaml编译器编写代码的。所以,我在写,这个语言特写,并经历了尝试上游的过程,当我这样做的时候,我的博士学位即将结束,Anil MadhaVapeddy正在四处寻找加入OCaml实验室的人,这是一个新的项目,致力于OCaml编译器,简·斯特里特在剑桥得到了某种程度上的资助。所以,他试图寻找从事OCaml编译器工作的人,突然,这个剑桥地址出现了OCaml的实现语言功能,所以他想,嗯,我应该去见见这个人。所以,他和我取得了联系。这就是我在完成博士学位后作为RA开始在OCaml实验室工作的方式。

顺便说一句,值得注意的是,大多数人都有智慧,不会立即开始为他们刚刚开始使用的语言添加功能,特别是潜心于类型系统。我想当Anil看到有人愿意进去添加一个新类型的系统特性时,他非常兴奋。

是。我当时没有意识到这不是你刚刚做的事情。是的,我在攻读博士学位时受到的监督有些不足,很明显,没有人告诉我这是一个糟糕的想法,也不是一个消磨时间的糟糕方式。所以,我就这么做了,我真的很享受。我是说,这是一个相当糟糕的…。比如,类型系统是很难深入研究的。我不建议在没有帮助的情况下做这件事。

你提到的你是如何参与到OCaml中来的,这件事总是让我有点担心语言是如何设计的,也就是说,语言几乎不可避免地是由编写编译器的人设计的,所以,他们四处寻找他们想要的编译器的功能,然后继续把它们添加到语言中,我总是在想,我们的语言是如何设计的,这有多大的偏见?

我会说,基本上不是很多,因为这可能是对OCaml的合理指责,OCaml非常适合编写编译器,并且拥有编写编译器所需的所有功能,但大多数语言并非如此。大多数语言编写编译器都有点可怕,所以我不认为它在那里适用。

所以,你从阅读类型和编程语言中对编程语言设计感到兴奋,这是本杰明·皮尔斯在这一领域非常著名的书,或者至少在极其狭窄的人群中非常著名,你已经做了很长一段时间了。其中一些工作是在你攻读博士期间完成的。一些在OCaml实验室,还有一些在这里,在中间时间。你觉得语言设计有什么令人兴奋的地方?你为什么喜欢它?

我认为我喜欢语言设计的主要原因之一是它位于一些非常有趣的纯数学之间有趣的交叉点,特别是

这是编程语言设计的真正挑战之一。从本质上讲,它真的不是一个科学事业,或者至少在结束时不是。这是你经常听到的编程语言人们抱怨的一件事,就是他们不能做任何适当的研究,或者更确切地说,他们做得到还是做不到,在实践中,这不是这个领域被驱动的方式。

有些人确实在尝试和研究编程语言的有效性,但它遇到了所有让社会科学实验变得困难的问题。只是看起来,原则上你可以做到,但是实验就是很难做,对吗?你真正需要做的是让大量的专业程序员同意在很长一段时间内使用所有这些不同的语言来解决相同的问题,显然这是不会发生的。

是的,在我看来,这确实是完全没有希望的,因为,如果你关心的事情是你可以在一种编程语言中做的事情,和一大群人在一起,解决困难的问题,花大量的时间在上面,这似乎是,至少在我看来,这是一个有趣的问题,我认为,一个许多编程语言甚至都没有动力的问题,你就没有希望了。就像人们在实践中可以进行的那种实验一样,他们抓起手头的东西,通常是大二学生的集合,然后他们研究他们能做的事情,比如理解他们在自己语言或喜欢的语言中看到的第一个错误有多容易,当他们在最初的几周或几个月的工作中尝试做一些事情时,他们做得有多好。当你思考是什么让编程在现实世界中有效时,这并不能触及你真正关心的事情。

我想,这确实困扰了很多从事编程语言工作的人。他们真的更希望这是一门恰当的科学。它更好地被认为是某种数学和设计的交叉点。这些都是我们知道如何学习的东西,对吗?科学方法并不是获取知识的唯一途径。有了数学,你可以尝试证明有用的定理和有趣的性质,人们成功地在设计学科中进行了研究,比如,我最喜欢的例子真的是建筑,我认为它是一个非常类似于编程语言设计的领域,因为它受到了数学的限制。你知道,从设计的角度来看,你必须确保建筑保持完好,而且很有趣。你知道,你想建造人们喜欢呆在里面和看着的建筑,等等。

而且,你需要检查的不仅仅是原始结构的东西。当你考虑一座建筑的设计时,你会想到交通时间是多少,人们会做各种各样的研究,试图了解它有多有效,但最终,没有人认为判断一座建筑是否好的最终方法是做一个随机对照试验,你就像,你设计了四个不同的建筑,然后你有了这个,这个和这个。你有四个等同的企业,你坐在四个不同的大楼里,你会看到它是如何发展的。我认为所需的经济投资的规模,我不确定做编程语言的等价物是不是不太荒谬或者更荒谬一些,但它是存在的。

我认为这是将编程语言设计作为一门学科来看待的一种更好的方式。

你知道,处理设计问题有两种方式。一是你可以在市场上解决,对不对?你可以,你知道,让人们去设计编程语言,看看哪些是成功的,我们已经记录下来了。有一套完整的系统可以做到这一点。还有一个与此相当的学术研究,特别是关于OCaml的许多工作,都是在包含大量学术内容的背景下进行的。你有没有感觉到,为了适应这种情况,你会如何让论文评估等事情与现在有所不同?

我没有具体的建议。我一直想,实际上是认真的,研究建筑学之类的学科,看看他们,我是说,他们是如何拥有期刊的。他们对事物有评估。他们肯定有这样做的机制,但我从来没有真正坐下来认真地花时间看看这是什么。更让我震惊的是,当你在,比如说ICFP,这是主要的函数式编程语言学术会议上,那里的人关心并认为在语言设计中有一些主题是重要的,而这些主题从来都不是演讲的主题。就像他们只会谈论事物的数学方面,或者可能是一些社会科学风格的实验的尝试,但他们永远不会在

那么,让我们稍微换一下方式。现在您已经花了很多时间来研究OCaml,您如何看待OCaml如何融入整个编程语言领域呢?

所以,首先,我想说,它是一种通用语言。人们使用的大多数编程语言都被描述为通用编程语言,但我想说在OCaml中尤其如此,它确实不一定在每个领域都是最好的。它在很多领域都很强大。您可以使用它来编写脚本。您可以将其用于低级高性能编程,并且在这两个领域中都可以获得相当大的收益。在它的识别特征方面,它具有很好的可预测性,我认为这一点非常重要。所以,我认为如果你找一位经验丰富的OCaml程序员,并向他们展示一些OCaml代码,他们很有可能大致告诉你所生成的程序集是什么样子;这是一个相当简单、可预测的编译故事。回到OCaml所处的位置,另一个可识别的特征是它有一个强大的类型系统。函数家族中相当多的语言都有这些强类型系统,但我认为这是OCaml的关键部分。就我个人而言,我认为如果没有强大的类型系统,我可能再也无法用一种语言编写代码了。随着时间的推移,它确实塑造了你对编程的思考方式。

它既会影响你设计东西的方式,也会让你养成把某些细心的习惯转移到类型系统上的习惯,然后你就会开始考虑其他事情,你就会变得不善于在你的大脑里跟踪这些东西。

是的,你还会花时间去做一些事情,比如相当下意识地构造代码,这样如果有错误,类型系统就会检查它。我最近注意到,当作用域中有两个类型相同的变量时,我可以感觉到,因为这就像是危险。你知道,就像,哦不。我可能会把他们弄糊涂。当这种情况发生时,我能真正感觉到,而在其他时间,哦,他们都是不同类型的。没关系,我不能真的搞砸了。不管怎样,强类型系统,最后一件事,我认为是OCaml独一无二的,或者至少是MLS独一无二的,那就是OCaml非常认真地对待模块性。那么,我这么说是什么意思呢?我的意思是,描述我所说的模块性的最好方法可能是谈论抽象。所以,抽象的定义本质上就是你有了某个系统,你想要做的就是把系统的一个组件替换成另一个组件,你这样做的机制是,你有一些接口的概念,它粗略地描述了一个组件的行为,当你用另一个组件替换一个组件时,你就用提供与另一个组件相同的接口的组件来替换它。因此,这种交换东西的能力非常强大,在OCaml的设计中非常普遍。

正确的。具体地说,有一个称为函数器的功能,它允许您实质上编写一个代码模块,该模块在不同的代码模块上进行参数化。

关键是在OCaml中,所有的东西都在模块中,所以,函数器,这是一个由另一个模块参数化的模块,所以基本上,就像一个从一个模块到另一个模块的函数一样,它们允许你参数化任何东西。因此,您可以提取程序的任何部分,并将其抽象为程序的任何其他部分。非常强大的想法,从语言设计的角度来看,它真的迫使你认真对待界面的想法。因此,与大多数语言不同的是,OCaml有用于实现和接口的单独文件,它有一种单独的、本质上是用于描述接口的语言,每当您想要向OCaml添加语言功能时,当您想要对其进行更改时,您必须认真考虑如何在接口和实现中表示该功能。所以,我见到了西蒙·佩顿·琼斯,他是GHC和Haskell的创始人之一,等等,我看到他做了一个演讲,他把Haskell的懒惰描述为穿着毛线衫。所以,在Haskell中,懒惰意味着当你写一个表达式来计算某个东西时,它不会立即被求值。它会等到你需要计算的结果,然后再评估它,这在避免做你实际上不需要的计算方面是有用的,但这意味着,你不能真正知道计算发生的时间。基本上,它们随时都有可能发生。

好的,在一种普通的严格语言中,你可以或多或少地看着程序说,我写下这个表达式,我写下那个表达式,或多或少,按照和程序的词汇文本相同的线性顺序,这就是事情执行的顺序。用一种懒惰的语言来说,这不像是假的

我只想解开一些术语。当我们谈到纯度和副作用时,纯粹的语言指的是一种不允许你表达副作用的语言,我们说的副作用指的是变异,或与外部世界互动之类的事情。Haskell非常重视明确说明程序的哪些部分是纯计算。只要计算一些东西,而不与世界上其他地方的程序的其他部分进行任何这种交互,并保持在这个纯子集上,并保持它是真正明确的,这是很好的,因为对于纯计算的推理比对带有效果的东西更容易。

是。一点儿没错。所以,不管怎样,我认为OCaml的模块性与之非常相似,它会影响你可以合理地将哪些语言功能添加到语言中,或者至少,它会影响那些语言功能的设计,因为你必须能够准确和方便地表达它们的界面,而许多语言的很多功能都不是这样的。

所以,Simon实际上已经说过Haskell,“下一个ML应该是纯净的,下一个Haskell应该是严格的”,根据我的理解,如果你现在建立一门新的语言,他会保持纯净,但他认为懒惰-严格是懒惰的反义词-懒惰不是他会添加到下一种语言中的一个特征。换句话说,他很高兴在Haskell中有懒惰,因为这真的让他们在纯洁性上投入了大量资金,但功能本身并不一定是正确的默认设置。我很好奇您对模块性的看法是否大致相同,也就是说,OCaml对模块性的关注是出于其自身的原因,还是出于它构建语言的方式,还是两者兼而有之?

所以,我会说两者都有。您将创建一个ML而不是…的想法。。

这是我的意见。所以,最近看起来有点ML风格的东西,可能是Rust,你知道,所以Rust最初的编译器是用OCaml编写的,所以,我非常肯定他们在写MLS的时候有一些经验,你可以在一些语言设计中看到一些经验,但它缺乏模块系统,所以,也许下一个ML没有模块系统,但我认为这是一个错误。“”。我认为这是“铁锈”的一个缺点,它让我很难过,也让我不太可能使用这种语言。这就是其中的一件事。这有点像是先有鸡还是先有蛋的问题。就像我不知道我使用OCaml是因为我喜欢模块化,还是我喜欢模块化是因为我使用OCaml。你知道,要解开它有点难。

是的,这就是语言设计中普遍存在的斯德哥尔摩综合症问题,就是你使用一种编程语言,你非常习惯它,很难跟踪你是因为使用了它的功能而喜欢它,还是因为你喜欢它而使用它。

好的,那么你认为模块性对于它自己的目的是有用的。它通过哪些方式对语言设计者施加道德压力?为什么语言设计人员在考虑如何抽象使用这些功能的代码片段时,不添加他们没有真正清晰的方式来表示接口的功能是好的呢?

不能在带有模块系统的语言中工作的语言特性的一个很好的例子是Haskell的类型类,对于那些不熟悉它们的人来说,它与Rust的特征系统非常相似。这是一回事。这些基本上都是用于进行即席多态性的系统#H。当您想要处理多个类型的单个函数时,这是某种程度上的多态性部分,但是您需要

.