Clojure写DSL
哲学
- 没有银弹,函数式编程也只是一种编程范式。
- 函数式编程的范式是申明式编程,关注于描述问题是什么而不是怎么实现。
- 函数式编程本质并不是高深的S-expr,Macro,不可变状态之类的特性,而是描述要干什么,而不是怎么干。
什么是DSL
DSL即领域编程语言,它是用于解决特定领域问题的语言。
为什么需要DSL
更好的描述问题是什么,增加语言的表现力。
为什么可以用Lisp来写DSL
- Lisp中数据即代码,代码即数据。
- 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"))
解释
- lisp是提倡自底向上设计的,如果没有思路,不妨从底层开始,如select函数和from函数。
- lisp的哲学每一层为上一层提供抽象愿语,如select和from函数为macro cljsql提供抽象原语。
总结:
Lisp 强大还是在于她本身的语言表现力,描述问题是什么,而不是怎么去做。