如今,Racket向用户承诺了面向语言的编程。但这个承诺有一个限制:如果你想构建一个宏可扩展语言,你的语言必须使用S表达式。这种限制是不公平的,因为告诉用户“你可以构建任何你想要的可扩展语言,只要它使用S表达式”,就像亨利福特告诉T型车买家“你的车可以是你想要的任何颜色,只要是黑色的。”我们想用一种新的编程语言来解除这个限制,同时借此机会改进Racktin向后不兼容的方式。
Rhombus是一个在Racket平台上构建宏可扩展通用编程语言的实验,该语言使用传统的表面语法和改进的库。
所谓“宏可扩展”,我们的意思是菱形用户应该能够扩展菱形的语法,就像Racket用户可以扩展Racket的语法一样。复杂的语法扩展,如对象和类系统、静态类型检查器和模式匹配,应该作为库来实现,同时仍然为其他语言中这些功能的用户提供熟悉的表面语法。
我们所说的“常规表面语法”是指对广泛使用的编程语言的用户以及熟悉基本数学符号的新手来说都是常规的。这导致我们面临以下限制:
函数调用被写成一个函数表达式,后跟一个用逗号分隔的参数列表,比如f(x,y,z)
额外的括号可以自由地用于分组和消除歧义,例如(1+2)*3,而不引入新的结构或语义。
句法形式是通过邻接而不是严格的层次结构连接起来的。例如do{}while()和x,其中y=z。这是一种“中缀”,比算术更广泛。
所谓“改进的库”,我们的意思是菱形不应该受制于Racket的向后兼容性约束。Rhombus应该可以自由创新,为其他语言中越来越常见的功能提供新的标准库,例如genericcollections、流处理和异步编程。
“在Racket平台之上”,我们的意思是,菱形应该像其他任何东西一样是一个#lang,用户应该可以将Hombus代码和库与普通Racket代码和库进行无缝组合。我们现在的处境
一些表面语法提案已经被头脑风暴,提案分为两大类:
类C的表面语法,使用大括号和分号**来表达一般结构。杰伊的C-表情符合这一类。
类似Python的表面语法,使用冒号和缩进来传达一般结构。Jay的lexprs和Matthew的灌木丛公证就属于这一类。
另外,还有一个问题,表面语法应该负责多少语法分组,而有多少分组取决于宏系统。有三种选择:
surface语法负责所有分组。这正是传统的S表达式所处的大致位置,很多Lisp都放松了S表达式对一切的约束,让宏创建隐式分组,这已经够尴尬的了。例如,Clojure的letform基于邻接性隐式地对绑定表达式对分组,如(let[x1y2](+xy))。Racket的关键字参数是放松此约束的类似实例。C表达式倾向于使用具有此属性的“常规表面语法”。
surface语法不负责分组。这会产生一种类似Forth的语法,其中程序只是一个简单的发音序列。这不符合我们的“常规表面语法”要求。
表面语法负责一些分组,但不是全部。这要求解析器理解程序的绑定和扩展宏,以获得程序结构的完整图片。以这种方式将令牌流的解析与宏扩展交织在一起称为enforestation,它允许宏扩展传统语言的语法。Honu研究语言是这项技术的先驱。
我们决定采用类似Python的带Enforestation的表面语法,特别是灌木状符号,作为第一个推进到下一个原型阶段的建议。这可能不是菱形项目的最终方向,但这是我们目前优先考虑的方向。我们是基于以下因素做出这一决定的:
缩进敏感度a la Python的优点是,屏幕上的可视分组与解析分组相匹配,但它也为运算符和标识符驱动的上下文敏感解析留下了大量空间。
Matthew尝试了几次实验,发现Python风格的符号最容易使用,到目前为止,他一直是primaryRhombus的实现者。
在这个阶段,对表面语法做出“正确”的决定并不是我们的目标。我们仍处于菱形项目的原型阶段。我们的目标是指出设计领域的领域,深入了解未来的挑战。因此,我们计划下一步围绕灌木丛公证建立一种语言。我们不相信灌木丛符号是完美的。尽管如此,我们相信,通过使用灌木符号构建一种工作编程语言所获得的理解将帮助我们进一步完善灌木符号。这对于确定哪些表面语法值得探索也至关重要。
要构建一门语言,我们需要编写库。我们可以研究的图书馆分为两大类:通用图书馆和专用图书馆。通用库是定义许多其他库(如类系统、并发抽象或泛型集合)的API所必需的。特殊用途的库特定于一个狭窄(但实际有用)的领域,例如文本解析或定理证明。特殊用途库更充分地利用了特定领域的语言,因此它们将让我们很好地了解Strubbery标记法与复杂DSL的配合情况。
图书馆是新的菱形贡献者加入的绝佳场所!我们仍处于早期阶段,因此探索同一问题领域的多种方法是有价值的。有各种各样的方向需要探索。以下是我们已经在不同程度上考虑的一些建议,但我们鼓励更多的建议。
菱形应该为通用集合提供公共数据结构,例如列表、集合、地图,以及用于对不同种类集合进行抽象的工具。拉克特的单态收集方式一直是一个长期的抱怨,这是少数几个社区几乎普遍同意需要改进的领域之一。
Rhombus应该提供更好、更统一的系统来定义新的数据类型和接口,而不是Racket当前的结构、类、泛型和结构类型属性的混乱。这里有很大的空间来利用灌木丛符号,尤其是如果我们要构建某种点转换器协议供宏使用的话。
注释、类型和契约。Racket的运行时契约和Typed Racket的静态类型处于动态静态正确性谱的两个极端。菱形能否占据更方便用户的中间地带?
多语言涂鸦。如果我们希望菱形库和Racket库能够无缝地互操作,我们需要一种Scribble到translatelibrary文档的方法,用于不同的表面语法。在sourcedocumentation中,这里可能也值得探索。