内部 DSL 风格
2006 年 10 月 24 日
内部 DSL(通常称为嵌入式 DSL)是在现有宿主语言中编写的 领域特定语言。这是一种在许多编程语言社区中常见的思维方式,特别是 Lisp 社区。随着 DSL 成为快速发展的 Ruby 社区中的一种常见思维方式,它现在正受到越来越多的关注。
当人们谈论内部 DSL 时,我看到了两种风格:内部微语言和语言增强。
内部微语言实际上是使用内部 DSL 来完成与使用外部 DSL 相同的事情。您有意识地决定使用 GPL 的一个子集来完成程序的微语言部分。它可能看起来像这样(来自我的 语言工作台 论文的示例)
mapping('SVCL', ServiceCall) do extract 4..18, 'customer_name' extract 19..23, 'customer_ID' extract 24..27, 'call_type_code' extract 28..35, 'date_of_call_string' end mapping('USGE', Usage) do extract 9..22, 'customer_name' extract 4..8, 'customer_ID' extract 30..30, 'cycle' extract 31..36, 'read_date' end
这都是有效的 Ruby 代码,但它使用 Ruby 的一个子集,使其看起来几乎像一个自定义 DSL。
与外部 DSL 不同,您受到宿主语言的语法和编程模型的限制,但您无需费心构建解析器。如果需要,您也可以在复杂的情况下使用宿主语言的功能。
使用内部 DSL 的另一种方式与您可能使用外部 DSL 的任何方式都截然不同。这是您使用 DSL 技术来增强宿主语言的地方。Ruby on Rails 的许多功能就是一个很好的例子。看看这些 Rails 验证代码
validates_numericality_of :age validates_uniqueness_of :ssn validates_format_of :length, :with => /^\d+(in|cm)/
阅读这些 Rails 验证代码,看起来我们已经为 Ruby 语言添加了新的关键字。当然,我们没有修改 Ruby,这都是巧妙的 元编程。但感觉就像我们增强了 Ruby 语言。
这两种技术都非常有用。与任何分类一样,它们之间存在模糊的界限(Rake 可以被认为是两种方式。)