clojure 表单是数据还是类型?
-数据
Clojure 表单是一段被视为数据的代码。
Clojure 形式具有化学性质。 元素类似于
- 数字(
42、3.1416、22/7)
- 字符串 (
"1, 2, buckle my shoe.")
- 符号 (
a5, freds-white-teeth),无论它们表示什么。
分子类似于
- 表达式(
(+ 1 1),(reduce * (range 1 n)))
- 参数列表(
[f coll],[[forename surname :as name]])
用于将分子形式绑定在一起的唯一结构是 Clojure 自己的数据结构。这就是 code as data 的含义。
Clojure 用途
- 表达式列表;
- 参数列表的向量(以及一般的绑定形式);
-
(关联绑定表单的映射)。
(暂时保留这些)。
在顶层,我们通常有def 和defn 表单。这些可以很深。
-
def 是一种特殊形式。它有自己的评估规则。
-
defn 看起来像一个特殊的形式,其实不是。
因为 Clojure 程序是作为 Clojure 数据编写的,所以我们可以编写函数
拼图的最后一部分是 Clojure 提供了一种特殊的函数模式,称为 宏,它
- 以表单形式对其参数进行操作
- 将调用表单转换为表单结果。
结果证明这是一种强大的机制。例如,defn 是一个将fn 表单包装在def 表单内的宏。一个廉价而愉快的类似物是
(defmacro my-defn [name & args-and-body]
(list 'def name (cons 'fn (cons name args-and-body))))
真正的defn 要复杂得多。不过这个就足够应付了
(my-defn twice [n] (* 2 n))
(twice 3)
;6
我们可以通过做来看看发生了什么
(macroexpand '(my-defn twice [n] (* 2 n)))
;(def twice (fn twice [n] (* 2 n)))
我们甚至可以定义递归函数:
(my-defn fact [n]
(if (pos? n)
(* n (fact (dec n)))
1))
(map fact (range 1 5))
;(1 2 6 24)
- 以上内容适用于任何 Lisp,不仅适用于 Clojure。
- 其他 Lisps 仅使用列表来构建表单。
- 没有其他重要的语言具有 code as data 属性。
- 函数式语言也不例外:ML 系列(ML、OCaml、
Haskell、F#、...) 具有相当传统的语法。