项目特定的DSL是否是责任?

时间:2011-08-13 20:09:16

标签: java api macros lisp dsl

我从一个类似的问题中提出了这个问题,这个问题是我对我收到的许多重要答案中的一个做出的评论。我最初询问AST宏,这主要引起了Lispers非常详细和深思熟虑的回应。感谢。

Lazy Evaluation vs Macros

我在评论中提出的问题是项目特定的DSL是否真的是一个好主意。当然,这是完全主观的 - 毕竟,当你用一种非常富有表现力的语言写作时,你在哪里画出富有表现力的API和实际的DSL?例如,我认为大多数Rubyist所谓的“DSL”实际上只是精心设计的API而已。

请注意,我说项目特定的 API。我认为很多人不会反对使用正则表达式或SQL,这样才有意义。

但是尽管如此,我认为我们都可以在API和DSL之间划出一条朦胧的线条。当然,它们都是真正的API,但无论如何。

在一个极端你有Lisp,似乎通过宏积极鼓励DSL。另一方面,你喜欢Java,而DSL几乎是不可能的。

DSL的支持者会争辩说,它们会增加灵活性,表现力并增加一致性(例如,使用与语言自己的数字相同的运算符的自定义数字对象)。

批评者会说他们可以导致除了DSL编写者之外没人知道的子语言,从根本上杀死了拥有不同编程语言的点,并导致代码无人能理解,因为接口的方式与API不同。

我得说,我在很多方面同意双方的意见。由于缺乏表现力,一些Java API只是简单的讨厌。尽管如此,我通常可以在不阅读文档的情况下总结出正在发生的事情 - 这对于定制的DSL来说是丝毫不可能的。也许DSL的支持者认为你应该总是阅读API文档。我不同意,但我也离题了。

但是让我们看一下目前的一些大语言。 C#和Java,即。他们俩都没有“做”DSL,但他们非常受欢迎。这是因为他们允许DSL之类的东西,允许平庸的编码人员制作出仍然可理解的代码?

DSL是否允许平庸的编码人员产生难以捉摸的垃圾,这就是为什么Lisp没有尽可能多地使用它的原因,尽管DSL可以在右手中看起来像什么?

2 个答案:

答案 0 :(得分:8)

当然有支持DSL和反对它们的论点,当然“图书馆”或“API”与“DSL”之间存在模糊界限。你在问题中已经涵盖了这一部分,所以我将避免这些主观观点,并专注于它们是否是一种责任的问题。

为此考虑的一个好项目是Racket,它以语言结构为主要特征。很容易为“语言”的任何定义提出一种语言:DSL或不是,通过解释器从近距离构成,或者(更常见地)通过定义新语言的宏来完成,并且可能是针对不同语法的解析器。因此,Racket源代码树有一堆语言 - 其中一些语言具有根本不同的执行语义。一些例子:

事实上,在Racket中编写语言非常容易,即使它适合非常有限的用途,甚至只是一个语言,你也可以轻松地编写语言。例如,我们有这样的“小语言”,用于创建我们的网页,决定分布式安装程序中包含哪些文件,以及更多。有关如何提供语言的说明,请参阅this tutorial

在许多人可以使用的有用DSL和只有一个人使用的DSL之间存在一条细线 - 但是,当你定义语言时,你可以得到的那种抽象而不是是实质性的,即使它是“一个人的语言”,它也是一个有用的概念。其中一个难题是考虑互操作性 - Racket允许每个模块用自己的语言编写,这会带来当这些模块中的一些模块相互通信时会发生什么问题。例如,当懒惰语言和默认语言中的函数交互时,评估是如何进行的;或者键入的内容如何确保它可以与默认的无类型语言进行交互,并且仍然可以获得静态类型语言的常用好处。

答案 1 :(得分:5)

DSL广泛用于Java。只是不是'内部'DSL。与Java不同,Lisp有几种方法可以在不编写新外语的情况下改变语言语法和语义。在Java中,大多数DSL都是外部的(通常基于XML)或使用预处理器实现。

如果您编写新的编程语言,也是特定于域的编程语言,则需要:

  • 指定
  • 记录
  • 测试
  • 让它变得健壮
  • make it debuggable
  • 提高效率 ......还有更多

Lisp并不是为你做这一切的灵丹妙药。 Lisp为您提供的是将一个或多个DSL直接包含在语言中,它允许您重用或更改Lisp工具以实现新语言的一部分。

Lisp在其历史上已经实现了很多语言。其中许多只是研究语言,没有太多努力来遵循软件工程实践。其中一些语言付出了更多的努力 - 例如,因为它们是产品的一部分。

如果您为项目开发语言,则需要确保遵循良好的软件工程实践,并且您有资源这样做。