语言设计师将如何决定或证明某个特定功能正常工作?


11

我对语言设计感兴趣,总的来说,我可以轻松地推断出广为人知的功能(例如继承,多态性,委托,lambda,捕获,垃圾回收,异常,泛型,方差,反射等),它们在特定的语言,可能的实现方式,限制等。

在过去的几个月中,我开始阅读Rust的知识,Rust具有一个所有权系统,该系统通过强制对象生存期为静态可验证的来确保内存安全和确定性资源管理。从普通用户的角度来看,我几乎可以立即使用该系统。

但是,从语言设计师的角度来看,我花了一段时间才意识到为什么Rust中的事物确实是这样。我无法立即理解所有权系统受到某些限制的原因,直到我强迫自己提出一些案例,如果这些系统不具备这些方面,就会侵犯系统的完整性。

我的主要问题与Rust及其所有权没有任何关系-但如有需要,可以随时在评论/答案中使用它作为示例。

语言设计师在设计新功能时,会使用什么方法或过程来确定该功能正常工作?

“新”是指它不是已经用现有语言测试过的东西(因此,大部分工作已由其他设计师完成)。“正常工作”是指该功能可以正确解决预期的问题,并且具有防弹功能。“合理地防弹”是指不能用该语言或该语言的特定子集(例如,没有“不安全”代码的子集)编写任何会破坏功能完整性的代码。

  • 从某种意义上说,这是一个反复试验的过程,即您提出了一种简单形式的功能,然后尝试找到方法来对其加以违反,如果成功违反了它,则对其进行修补,然后重复进行?然后,当您无法想到任何其他可能的违规时,您希望什么都没有了,可以称之为一天?

  • 还是有一种正式的方法(从字面上的数学意义上)实际证明您的功能有效,然后使用该证据从一开始就确信该功能正确(或基本上正确)?

(我应该提一下,我具有工程学背景,而不是计算机科学。因此,如果我错过了CS人士显而易见的东西,请随时指出。)


当您说“语言设计者”时,您是指创建编译器的人,还是仅创建语法的人,或两者兼而有之?
史努比

6
@StevieV:语言设计与实现不同,并且独立于实现。例如,约翰·麦卡锡(John McCarthy)将Lisp设计为更容易掌握λ微积分的替代方法。但是,他没有实现它。实际上,当他的学生史蒂夫·罗素(Steve Russell)想要实施Lisp时,麦卡锡告诉他,他认为不可能实施Lisp!APL被设计为一种用于数学教学的语言。后来,IBM使用它来正式指定System / 360的行为,为此语言提供了多种扩展。目前,它尚未实现。Plankalkül的设计是由康拉德
约尔格W¯¯米塔格

4
Zuse 1942-1946,但在1975年才实施。Niklaus Wirth最初完全设计了他的语言,并且仅在完成设计后才实施它们(他用该语言本身编写了第一个编译器,以了解该语言的性能如何。设计-然后他让他的学生将编译器手动翻译为另一种语言以进行引导)。从未实施过更多的学术语言,它们只是设计用来以抽象的方式证明观点或尝试某些语言功能。Smalltalk的创建为一个相互打赌的结果:阿兰凯确信他能够
约尔格W¯¯米塔格

3
在单页纸上设计一种面向对象的语言时,丹·英加尔斯(Dan Ingalls)押注,他可以在几天内实现该语言。(而且他用所有语言都用BASIC做到了!)语言是数学对象,它们独立于其编译器/解释器而存在。而且可以独立于任何物理实现来设计,研究和讨论它们。
约尔格W¯¯米塔格

3
必须阅读:Godel,Escher,Bach。有时这有点奇怪,但是到最后,Turing&Godel的大部分工作都极大地影响了语言设计的形式化。
RubberDuck

Answers:


6

目前,我很难找到确切的参考资料,但不久前,我观看了由西蒙·佩顿·琼斯Simon Peyton Jones)拍摄的几段视频,他是Haskell设计的主要贡献者。顺便说一下,他是类型理论,语言设计等方面的杰出演讲者,并且在youtube上有许多免费的视频。

Haskell具有一个中间表示形式,该表示形式实际上是lambda演算,其中添加了一些简单的东西以使其更易于使用。由于计算机只是一个计算事物的人,因此Lambda演算已得到使用和证明。西蒙·佩顿·琼斯(Simon Peyton Jones)经常提出的一个有趣的观点是,只要他们对这种语言疯狂而疯狂地做某事,他就知道从根本上讲,当语言最终还原为该中间语言时,这是基本的声音。

其他语言并不是那么严格,而是倾向于易于使用或实现。他们做其他程序员为获得高质量代码所做的相同工作:遵循良好的编码习惯并对其进行测试直至死。我敢肯定,Rust的所有权语义之类的功能会得到大量形式化分析和测试,以发现被遗忘的极端情况。通常,此类功能始于某人的毕业论文。


2
我相信您要查找的参考文献是“ Haskell中的类型冒险”系列之一,可能这是在缩略图中给出了董事会内容的原因……
Jules

8

因此,对于语言设计,有证明(或错误)。例如,键入系统。《类型和编程语言》是描述类型系统的经典书籍,着重于证明类型系统的正确性和完整性。语法有类似的分析,算法(如您描述的所有权系统)也有自己的语法。

对于语言实现,它是任何其他代码。您编写单元测试。您编写集成测试。您进行代码审查。

使语言特别的唯一原因是(几乎总是)它们是无限的。您实际上无法测试所有输入。并且(理想情况下)它们被成千上万的人所使用,做了奇怪而有趣的事情,因此最终发现该语言中的任何错误。

实际上,很少有语言使用证明来验证其功能,并最终将您提到的选项混合在一起。


4
The only thing that makes languages special is that they are (almost always) infinite. You literally cannot test all inputs.真的那么特别吗?在我看来,这是常见的情况。例如,以列表为参数的函数也具有无限数量的输入。对于您选择的任何大小n,都有一个大小n + 1的列表
。– Doval

@doval-我想也是字符串。好点。
Telastyn

4

语言设计师在引入新功能时必须注意的第一件也是最困难的事情是保持其语言的一致性:

  • 如何在不破坏现有代码的情况下将其集成到语言语法中(可以通过数学证明)
  • 它与现有特征的关系(例如,如果您有索引为0..n-1的固定数组,则不会引入索引为1..n的新可变数组特征)(这是设计的艺术部分)
  • 如何在整个工具链中实现功能,以便生态系统,工具制造商和程序员可以吸收新功能(可以通过概念验证来证明可行性,但是完全实现是类似于编程的方法)

为了对此进行指导,设计人员依赖于一组设计规则和原则。这种方法是在很好的描述中的C设计和演变++由Bjarne的Stroustrup的”,专用于语言的设计善本之一。有趣的是,很少有语言是在真空中进行设计的,而且设计师还希望他们的语言如何实现类似的功能。另一个来源(在线和免费)是java语言设计原理

如果您查看标准化委员会的公开程序,将会发现它更多是一个审判错误过程。这里是C ++模块上的一个示例,它将在该语言的下一版本中引入一个全新的概念。此处是在一些语言更改后起草的一项分析,以评估其成功。这里是Java社区流程,用于定义新的Java规范,例如新的api。您将看到这项工作是由多位专家完成的,他们创造性地起草了概念文件和第一个建议。然后,较大的社区/委员会将对这些建议进行审核,该社区/委员会可对建议进行修改以确保更高的一致性。


4

如何测试编程语言功能?这是一个很好的问题,我不确定最新技术是否能胜任。

每个新功能都可以与所有其他功能交互。(这会影响语言,文档,编译器,错误消息,IDE,库等。)功能组合是否会造成漏洞?要创建令人讨厌的边缘案例?

即使是非常聪明的语言设计师,他们也在努力保持类型的完整性,也会发现诸如Rust错误之类的违规行为。Rust的类型系统对我而言并不那么明显,但我认为在这种情况下,具有类型系统跟踪值生命周期的生命周期意味着生命周期的“子类型化”(子范围)与对常规子类型化,强制,引用和可变性的期望相冲突,从而在整个static生命周期中造成了漏洞ref可以指向堆栈分配的值,后来成为悬挂的引用。

“正常工作”是指该功能可以正确解决预期的问题,并且具有防弹功能。

对于打算用作生产语言的语言,即许多程序员用来构建可靠的生产软件的语言,“正常工作”必须进一步意味着为目标受众正确解决目标问题

换句话说,可用性对语言设计和其他类型的设计一样重要。这需要(1)可用性设计(例如,了解您的听众),以及(2)可用性测试。

关于该主题的示例文章是“ 程序员也是人,编程语言和API设计人员可以从人为因素设计领域中学到很多东西。”

关于此主题的SE问题示例是:是否已测试了任何编程语言的语法的可用性?

一个示例可用性测试考虑了扩展列表迭代功能(我不记得哪种语言)来获取多个列表。人们是否期望它并行地或通过交叉产品遍历列表?语言设计人员对可用性测试的发现感到惊讶。

诸如Smalltalk,Python和Dart之类的语言在设计时着重于可用性。显然,Haskell不是。


Haskell实际上非常有用。很难学习,因为它是与Python / C / Java等完全不同的范例。但是,作为一种语言,它非常易于使用。
分号
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.