內部 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 可以被認為是兩者之一)。