API和嵌入式领域特定语言(DSL)有什么区别?
只是语法吗?
考虑像OpenGL这样的API。与图形DSL有何不同?
换句话说,如果API足够复杂,是否可以将其视为嵌入式DSL?
API和嵌入式领域特定语言(DSL)有什么区别?
只是语法吗?
考虑像OpenGL这样的API。与图形DSL有何不同?
换句话说,如果API足够复杂,是否可以将其视为嵌入式DSL?
Answers:
很难区分,并且取决于所使用的语言。这也是主观的。
在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,但是其中一些库的设计不佳:-)
API和DSL是完全不同的概念,在某些领域中可以说它们重叠。
所有DSL都是计算机语言。它们可能是解释语言,编译语言,标记语言,查询语言(例如SQL)或(例如JSON或XML的某些用法)数据语言,它们可能在通过API传递的消息中使用,但它们必须是语言。该术语描述的是本质,而不是目的。
API是允许一个软件组件被其他组件使用的接口。该术语描述的是目的,而不是本质。API可以是一组对象方法,例如- 不是 DSL。Web API可能使用DSL(或者,如果很安静,您可能会说它是 DSL),但是共享的,特定于域的语言不是该定义的一部分。设备的软件驱动程序可以用C编写,API作为已编译的库分发,协议完全是二进制的,并且可以使用该库的任何语言都可以用作客户端。该API中没有任何东西可以称为DSL(API函数的符号名称列表不会削减它)。
在给定定义的情况下,为什么您只能看到相似之处,我有些困惑。
一般来说,没有。为了使某些操作更加方便,故意将DSL设为非通用。诸如HTML或徽标之类的东西最初是特定于域的语言。
通常,即使使用最强大的API,也无法将DSL嵌入另一种语言。无论您使用该API编程的内容如何,仍然看起来像是宿主语言中的一系列表达式,并且不如使用专用语言那样方便。
例外情况是,这些语言提供了通过库来扭曲语法的特殊机会(运算符重载,例如C ++,发明了新的运算符,例如Scala,甚至预先声明了完全不同的读取语法,例如带有源过滤器的Perl)。当您使用这样的语言并充分利用它们提供的灵活性时,结果看起来可能像是一种新的特殊用途的语言(但是语义通常会与真正发明该语言时所期望的有所不同)从头开始为您的目标服务)。
在这里,来自Martin Fowler的DslBoundary
从这篇文章中,我的理解基本上是嵌入式DSL和API并没有太大区别。但是,这里有些不同。
但是,如果谈论外部DSL,那就另当别论了。外部DSL就像一种小型编程语言一样,但是可以肯定的是,它不是通用语言,它不能解决所有问题,而只能解决特定问题。
我认为每个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。