Clojure写DSL

Clojure写DSL

哲学

  1. 没有银弹,函数式编程也只是一种编程范式。
  2. 函数式编程的范式是申明式编程,关注于描述问题是什么而不是怎么实现。
  3. 函数式编程本质并不是高深的S-expr,Macro,不可变状态之类的特性,而是描述要干什么,而不是怎么干。

什么是DSL

DSL即领域编程语言,它是用于解决特定领域问题的语言。

为什么需要DSL

更好的描述问题是什么,增加语言的表现力。

为什么可以用Lisp来写DSL

  1. Lisp中数据即代码,代码即数据。
  2. Lisp的Macro可以让你定义自己的控制结构,写出自己的编程语言。

例子

Clojure实现一个Sql的DSL

(ns clojuresql.core)

;;; jdbc 驱动
(require '[clojure.java.jdbc :as jdbc])

;;; 数据库配置
(def db-spec {
              :subprotocol "mysql"
              :subname "//172.17.8.101:3306/didi_db"
              :user "admin"
              :password "root"})

;;; Select 语句处理
(defn select
  [fields]
  (clojure.string/join
   " "
   (concat
    ["SELECT"]
    [(clojure.string/join
    ", "
    fields)])))

;;; from 语句处理
(defn from
  [& table]
  (clojure.string/join " " (concat ["FROM"] table)))

;;; 定义控制结构
(defmacro cljsql
  [& sql_atom]
  `(jdbc/query
    db-spec
    [(clojure.string/join " " (list ~@sql_atom))])
  )

;;; 使用
(cljsql (select ["username", "password"])
        (from "auth_user"))

解释

  1. lisp是提倡自底向上设计的,如果没有思路,不妨从底层开始,如select函数和from函数。
  2. lisp的哲学每一层为上一层提供抽象愿语,如select和from函数为macro cljsql提供抽象原语。

总结:

Lisp 强大还是在于她本身的语言表现力,描述问题是什么,而不是怎么去做。