Java 特定于项目的DSL是一种责任吗?

Java 特定于项目的DSL是一种责任吗?,java,api,macros,lisp,dsl,Java,Api,Macros,Lisp,Dsl,我把这个问题从我在评论中提出的一个类似问题转移到我收到的许多伟大答案中的一个。我最初问的是AST宏,它引起了Lispers非常详细和深思熟虑的回答。谢谢 我在评论中提出的问题是,特定于项目的DSL是否真的是一个好主意。当然,这完全是主观的——毕竟,当你用一种真正有表现力的语言写作时,你在表现力的API和实际的DSL之间划出了什么界限?例如,我认为大多数Rubyists所称的“DSL”实际上只是设计良好的API而已 请注意,我说的是特定于项目的API。我认为很多人不会反对在有意义的地方使用正则表

我把这个问题从我在评论中提出的一个类似问题转移到我收到的许多伟大答案中的一个。我最初问的是AST宏,它引起了Lispers非常详细和深思熟虑的回答。谢谢

我在评论中提出的问题是,特定于项目的DSL是否真的是一个好主意。当然,这完全是主观的——毕竟,当你用一种真正有表现力的语言写作时,你在表现力的API和实际的DSL之间划出了什么界限?例如,我认为大多数Rubyists所称的“DSL”实际上只是设计良好的API而已

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

但尽管如此,我认为我们都可以在API和DSL之间划出一条模糊的界限。当然,它们都是真正的API,但不管怎样

一个极端是Lisp,DSL似乎通过宏得到了积极的鼓励。另一方面,您也可以使用Java,在Java中DSL几乎是不可能的

DSL的支持者会争辩说,DSL增加了灵活性、表达性和一致性(例如,自定义数字对象使用与语言自身数字相同的运算符)

批评者会说,它们会导致除了DSL编写者之外没有人知道的子语言,扼杀了使用不同编程语言的必要性,并导致没有人能理解的代码,因为与API接口的方式不同

我得说,我在很多方面都同意双方的观点。由于缺乏表现力,一些JavaAPI非常糟糕。尽管如此,我通常不需要阅读文档就可以知道发生了什么——这一点也不能说是关于定制DSL的。也许DSL的支持者认为您应该总是阅读API文档。我不同意,但我也离题了

但让我们看看目前的一些主要语言。C#和Java,即。它们都不是真正的“做”DSL,但是它们非常流行。这是否正是因为他们不允许像DSL这样的东西,允许平庸的程序员大量生产出仍然可以理解的代码


DSL允许平庸的程序员产生无法穿透的垃圾,这是不是Lisp没有得到应有的使用的原因,尽管DSL在右手中看起来像什么?

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

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

  • 具体说明
  • 记录下来
  • 测试一下
  • 让它变得健壮
  • 使其可调试
  • 让它更有效率 ... 还有更多
Lisp不是为你做这些的灵丹妙药。Lisp为您提供的是将一个或多个DSL直接包含到语言中,它允许您重用或更改Lisp工具以实现新语言的一部分

Lisp在其历史上有很多语言是在它之上实现的。他们中的许多人只是研究语言,没有花太多精力去遵循软件工程实践。其中一些语言投入了更多的精力——例如,因为它们是产品的一部分


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

当然有赞成和反对DSL的论据,当然,“库”或“API”和“DSL”之间有一条模糊的界线。你在问题中已经很好地涵盖了这一部分,所以我将避免这些主观观点,只关注它们是否是一种责任的问题

这是一个值得考虑的好项目,它以语言结构为主要特征。对于“一种语言”的任何定义,都很容易建立一种语言:DSL与否,通过解释器或(更常见的是)通过定义新语言的宏(可能还有一个不同语法的解析器)从头开始构建。因此,Racket源代码树有一系列语言——其中一些具有根本不同的执行语义。一些例子:

  • 这就是你所期望的名字的意思

  • 是一种静态类型的语言

  • 是一种用于编写文档和其他散文的语言

  • 是一种用于写作的语言。。。幻灯片

  • /是在语义和语法上更为不同的语言

事实上,编造语言是如此的容易,以至于你可以很容易地把一种语言拼凑起来,即使它适合非常有限的用途,甚至是一种单一的用途。例如,我们有这样的“小型语言”,用于创建网页、决定分布式安装程序中包含哪些文件,等等。有关如何生成语言的说明,请参见

的确,许多人可以使用的有用DSL和只有一个人使用的DSL之间有一条细微的界限——但是,当你定义一种语言而不是一个库时,你可以得到的抽象是实质性的,甚至当它是“一个人的语言”时,它也是一个有用的概念。其中一个困难的问题是考虑互操作性——Racket允许每个模块用自己的语言编写,这就带来了当这些模块中的几个模块应该相互对话时会发生什么的问题。例如,在惰性语言和默认语言中存在函数交互时,如何进行求值;或者怎么做