优雅同熟悉正交
—— Rich Hickey
开始Clojure编程之前 需要预先配置环境 开发Clojure 只需要JDK和一个Clojure库
开发和运行 Clojure 程序有两种常用方式 其中最常用的一种方法是使用它的 REPL(read-eval-print-loop)
下载Clojure发行版 解压进入 运行REPL命令
➜ clojure-1.6.0 java -cp clojure-1.6.0.jar clojure.lang.Repl WARNING: clojure.lang.Repl is deprecated. Instead, use clojure.main like this: java -cp clojure.jar clojure.main -i init.clj -r args... Clojure 1.6.0 user=>
java -cp clojure-1.6.0.jar clojure.main /tmp/test.clj //启动/tmp/test.clj
LISP就是列表处理的意思 Clojure又是JVM上的LISP方言 从此可见 Clojure中列表也是极重要的一种结构
就如同文件对于linux系统 Clojure中一切都可以认为是列表
如果我们要列出 10 以下且为 3 或 5 的倍数的所有自然数,我们将得到 3、5、6 和 9。这几个数的和是 23。
我们要求出 1,000 以下且为 3 或 5 的倍数的自然数的和。
首先 我们定义一个函数用于判断一个数字是否是可以被3或者5整除的
(defn divisible-by-3-or-5? [num] (or (== (mod num 3) 0)(== (mod num 5) 0)))
需要提醒一点 defn 并不是一个函数 它是一个宏 宏允许在语言层面扩展Clojure 向其中添加关键字
宏和函数之间有什么区别? 这点我在后续会详细解释
Clojure或者说LISP使用-分割命名方式 (在定义协议的时候使用驼峰命名 因为这样和Java虚拟机交互命名方式一致)
使用?结尾 表示这个宏是一个断言 返回值为true或者false []内的num表示宏接收一个参数
(or (== (mod num 3) 0)(== (mod num 5) 0))) 是函数体
翻译过来也就是 ((num mod 3) ==0 ) or ((num mod 5) ==0 )
or 是一个函数 这点和Scala是一样的 不是Java中的操作符 同样==和mod 也是函数
(println (reduce + (filter divisible-by-3-or-5? (range 1000))))
这行从内向外看 range 1000创建一个[0,9999]的序列
写到这儿是不是体会到一些Java和Clojure的不同了呢?
表象是中缀表达式和前缀表达式的区别 其实不然 运算的顺序并没有改变
Clojure允许定义惰性序列,也就是在真正需要的时候才进行计算 这也就是说 你可以从中定义无穷序列
Clojure作为函数式编程语言 对于函数的广泛支持自然是必不可少的 就如同Java对于Class一样 都是程序运行的基础
(println (reduce + (filter even? (take-while (fn [n] (< n 4000000)) (lazy-seq-fibo)))))
参考文献:
[0] Clojure 编程语言
https://www.ibm.com/developerworks/cn/opensource/os-eclipse-clojure/