Không có mẫu đặc biệt cho DSL - bạn chỉ mất công cụ có sẵn trong ngôn ngữ và cố gắng làm cho nó như thuận tiện và gần gũi với lĩnh vực càng tốt. Lisp chỉ cung cấp cho bạn nhiều công cụ hơn các ngôn ngữ khác.
Ví dụ cụ thể về giao diện DSL đẹp tại ClojureQL. Ban đầu, SQL được tạo thành DSL cho cơ sở dữ liệu quan hệ. Và nó rất thuận tiện để làm việc từ bàn điều khiển ... nhưng không phải từ ngôn ngữ lập trình như Java hay Clojure. Java đi kèm với các khuôn khổ ORM lớn như Hibernate, và Clojure cung cấp DSL đơn giản đó là thuận tiện như SQL gốc, nhưng hoạt động hoàn toàn như một phần của ngôn ngữ:
(select (table :users) (where (= :id 5)))
điều thường gặp trong Lisp DSL đang sử dụng cấu trúc như defsomething
. Ví dụ, trong một cuốn sách (xin lỗi, tôi không nhớ tên của nó) có một ví dụ về khớp mẫu trong văn bản. Tác giả tạo mô-đun với một số đối sánh như ?
cho một từ, +
cho một hoặc nhiều từ, *
cho 0 hoặc nhiều từ hơn, v.v. Vì mục đích này, anh ta tạo macro defmatcher
để thực hiện cú pháp và thêm trình xử lý cho cú pháp này vào sổ đăng ký trung tâm. Đây chỉ là trừu tượng - thay vì một số hoạt động lặp đi lặp lại, ông giới thiệu đơn macro nói với những gì ông thực sự muốn làm - xác định matcher. Ngoài ra ví dụ này sử dụng cả hai - macro và các hàm bậc cao.
Vì vậy, một lần nữa, không có gì đặc biệt trong các DSL dựa trên Lisp - bạn chỉ cần mô tả khu vực miền bằng các công cụ bạn có bằng ngôn ngữ của mình, có thể là Java, Clojure hay bất kỳ thứ gì khác. Chỉ cần làm quen với các cơ sở ngôn ngữ và bạn sẽ thấy nó trông như thế nào.
UPD. Một số "thực tế" ví dụ nơi DSL Lisp-based được thuận tiện hơn, chẳng hạn, OOP:
miền: xe dillership
(defcar my-cool-car :wheels 4, :doors 2, :color red) ;; in Java you need Factory
(def car1 (make-car my-cool-car)) ;; and lots of methods to
;; add features to cars and
;; cars to factory
miền: hệ thống thanh toán
(transaction ;; in Java you cannot create wrapping constructs
(withdraw account1 100) ;; so you have to use inheritance, annotations, etc.
(put account2 100)) ;; which is much more code
miền: một số dịch vụ web xử lý các yêu cầu của một số loại
(defhandler :show-all (fn [params] ...)) ;; adds defined function to the
(defhandler :find-best (fn [params] ...)) ;; map of :message-type -> function
...
(defn handle [message]
(let [msg-type (:type message), msg-params (:params message)]
(if (contains? *handlers* msg-type)
((*handlers* msg-type) msg-params)
(throw (Exception. (concat "No handler for type" (:type message)))))))
Không có điều đặc biệt về những ví dụ này - bạn có thể thực hiện tất cả chúng bằng Java hoặc bất kỳ ngôn ngữ nào khác. Mặc dù, những thứ như từ khóa (ví dụ 1), các hàm bậc cao hơn (ví dụ thứ 2), các macro (tất cả 3 ví dụ) làm cho bạn mã súc tích và mô tả hơn.
... lancet là một DSL, nhưng nó không thực sự là một "thế giới thực" vấn đề trong đó hầu hết các lập trình viên chưa bao giờ cố gắng để viết một hệ thống như vậy: Kiểm tra tốt ol 'google: ứng dụng jpetstore .... – jayunit100