什么时候将API视为嵌入式DSL?


10

API和嵌入式领域特定语言(DSL)有什么区别?

只是语法吗?

考虑像OpenGL这样的API。与图形DSL有何不同?

换句话说,如果API足够复杂,是否可以将其视为嵌入式DSL?


1
DSL的目的是使事情变得更简单。您是否应该问一个足够简单的 API是否可以视为DSL?
2014年

我想我想知道/理解的是API和DSL的区别。我在其中添加了复杂内容,因为我认为当人们不断地对一种API进行调用时,它相当特定于域,或者至少这就是我最初的想法。
Phyllostachys

1
问题是,API嵌入式DSL有什么区别?
proskor 2014年

Answers:


8

很难区分,并且取决于所使用的语言。这也是主观的。

在clojure中,您可以定义看起来像DSL的API。例如,打ic允许您生成html:

(html [:span {:class "foo"} "bar"])

可以将其视为具有Lisp语法的DSL。html可能是宏的事实赋予了它相同的功能,就好像您正在编写带有s-expressions的html模板库(请参阅sxml

在python中,相同的API可能如下所示:

html(["span", {"class" : "foo"}, "bar"])

html是一个函数。首先将评估其参数,然后进行函数调用。python语法更具体,而python语义更严格的事实意味着该表达式更难解释为独立于该语言的DSL。

经典的语言表示形式是像树一样的数据结构和在其节点上递归调用的eval函数。LISP语言使这种树结构非常明显,因此任何嵌套函数调用都无法与内置语言功能区分开。这就是LISP社区谈论几乎所有内容的DSL的原因。

我相信编程是关于提供有用的抽象的。我发现,将构建的所有内容(lib甚至是应用程序的UI)视为帮助人们解决复杂问题的语言元素是设计大多数事物的有效方法。从这个角度来看,我断言每个库都是DSL,但是其中一些库的设计不佳:-)


4

API和DSL是完全不同的概念,在某些领域中可以说它们重叠。

所有DSL都是计算机语言。它们可能是解释语言,编译语言,标记语言,查询语言(例如SQL)或(例如JSON或XML的某些用法)数据语言,它们可能在通过API传递的消息中使用,但它们必须是语言。该术语描述的是本质,而不是目的。

API是允许一个软件组件被其他组件使用的接口。该术语描述的是目的,而不是本质。API可以是一组对象方法,例如- 不是 DSL。Web API可能使用DSL(或者,如果很安静,您可能会说它 DSL),但是共享的,特定于域的语言不是该定义的一部分。设备的软件驱动程序可以用C编写,API作为已编译的库分发,协议完全是二进制的,并且可以使用该库的任何语言都可以用作客户端。该API中没有任何东西可以称为DSL(API函数的符号名称列表不会削减它)。

在给定定义的情况下,为什么您只能看到相似之处,我有些困惑。


正如评论员所指出的,我必须只考虑嵌入式DSL。考虑一下像Forth这样的东西,其中有人构建了单词词典。我已经读到,随着建立DSL接近具有完整功能的应用程序,它似乎很像API。
Phyllostachys 2014年

2
这实际上并没有影响我的回答。如果它是一种语言,具有自己的语法等,则它是DSL。缺少那些语言功能的复杂接口不是DSL。您可能应该更新您的问题,我将考虑更新我的答案。
itsbruce 2014年

2
子语言仍然是一种语言。不必具有“自己的”语法,它可以从宿主语言“借用”它。
proskor 2014年

那么,在即将完成时,不是所有项目都属于自己的DSL吗(即通用编程语言最终就是DSL)吗?从一般到特定领域的各种连续体。
Phyllostachys 2014年

4

一般来说,没有。为了使某些操作更加方便,故意将DSL设为非通用。诸如HTML或徽标之类的东西最初是特定于域的语言。

通常,即使使用最强大的API,也无法将DSL嵌入另一种语言。无论您使用该API编程的内容如何,​​仍然看起来像是宿主语言中的一系列表达式,并且不如使用专用语言那样方便。

例外情况是,这些语言提供了通过库来扭曲语法的特殊机会(运算符重载,例如C ++,发明了新的运算符,例如Scala,甚至预先声明了完全不同的读取语法,例如带有源过滤器的Perl)。当您使用这样的语言并充分利用它们提供的灵活性时,结果看起来可能像是一种新的特殊用途的语言(但是语义通常会与真正发明该语言时所期望的有所不同)从头开始为您的目标服务)。


因此,也许可以做一个解析字符串(DSL)的事情,该字符串充当大型API的简单包装。我认为DSL与解析DSL的区别是区别。
Phyllostachys 2014年

3
是的,这被称为“解释器”设计模式,并且被认为是一种很好的做法:您只需编写一次解释器代码,然后就可以更轻松地表达特定于域的内容。
Kilian Foth,2014年

“发明像Groovy这样的新运算符”也许您的意思是Scala。在Groovy中,运算符集是固定的,但可以像在C ++中那样重载。
Vorg van Geir 2014年

@VorgvanGeir对不起,已修复。
Kilian Foth,2014年

2

在这里,来自Martin Fowler的DslBoundary

从这篇文章中,我的理解基本上是嵌入式DSL和API并没有太大区别。但是,这里有些不同。

  1. API强调提供新功能。
  2. DSL不仅为您提供了新的功能,还为您提供了新的语法和编码的新方法。

但是,如果谈论外部DSL,那就另当别论了。外部DSL就像一种小型编程语言一样,但是可以肯定的是,它不是通用语言,它不能解决所有问题,而只能解决特定问题。


1

我认为每个API都是嵌入式DSL,但事实并非如此:并非每个嵌入式DSL都是API。仅当该语言用作集成组件的方法时,才可以称为API。

为什么将API视为嵌入式DSL?首先,它形成一种语言:它具有原始元素(类型和操作),可以将其组合(通过宿主语言)以形成抽象并解决复杂的问题。例如,OpenGL API可用于实时渲染3D场景。可以使用Collections API创建对对象集等进行操作的算法。例如,Collections API的域是处理对象集,而OpenGL API的域是3D渲染。因此,API是领域特定的语言。

但并非每个DSL都是API。例如,某些DSL不能由指定的组件实现。所有系统都定义了一些抽象,并且处理某些特定域的抽象可以视为DSL,但这并不意味着这些抽象的实现应是“可交换的”,换句话说,它们不必形成API。 。他们可以,但这并不总是必要的。但是,在实现是“组件化”的情况下(抱歉,没有更好的用语),DSL确实变成了API。


这仅仅是您的意见,还是可以通过某种方式予以支持?
蚊蚋

@gnat我扩展了答案以进一步解释我的观点。
proskor 2014年
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.