getting started
|
|
|
|
Clojure 是 Lisp 对 JVM 的抱大腿行为
我猜,由于 Clojure 是 Lisp 方言的原因,在国内,Clojure 的使用真的很少很少,cn-clojure 这个国内的 Clojure 用户组的人气也不高。
于是,我提了一个问题, Clojure的发展情况如何? ,也做了些查询,汇总下信息
Clojure 的很多代码都是银行的业务作为例子,比如下面这个,所以以为会有比较多的金融行业应用,但是实际上没看到。。。
|
|
|
|
搜索了下国外的情况,其实应用也不多,有 citi (花旗银行)、 UBS (瑞士联合银行) ,但是好像实际用的也不多。有一段评价[2]:
Based on my own experience and conversations with others who work in the City, there’s a small but increasing move towards functional languages. I have to say that by far the most common I’ve heard of are Scala or F#, with ML and Clojure far behind.
也就是说金融行业虽然也在往函数式语言靠,但是F# 和 Scala 的使用更广泛,远高于 ML 和 Clojure 这样的语言。
[1] http://chaifeng.com/clojure-stm-what-why-how/
[2] http://mdavey.wordpress.com/2013/05/24/clojure-in-finance/ 的评论
|
|
|
|
|
|
像上面的 doc
、find
等函数需要 use
才能使用,为方便起见,可以在repl启动时,就载入,只需在 ~/.lein/user.clj
添加
|
|
这样,每次启动 repl 都能直接使用这些函数了
Clojure 是一种基于 Java 虚拟机 (Java Virtual Machine)的动态编程语言,支持函数式编程,简化并发编程,能调用 Java 程序
什么函数式编程?程序的功能单位是无副作用的函数,输入确定,输出就确定,就像数学上的函数一样。
相对传统的面向对象方式——复杂的对象关系图,基于状态变量,函数式编程提供了另外一种解决问题的思路。
use
和 require
引入非核心库
|
|
一个判断是否是空字符串的函数
用Java 来写:
|
|
用Clojure 来写:
|
|
短小多了吧!
值得的注意的是,Clojure版本的代码,噪音非常低,而Java的看起来很啰嗦,使用了更多的语法关键词,如 public
, class
, boolean
等
与 Java 等其它 C 系的语言不同,Clojure 中 ?
也是可以作为函数名字的,Lisp系的语法关键词要少,因此显得简单优雅,这种简单优雅,是因为 Lisp 语言的构成单位括号表达式所带来的,括号表达式对与很多人来说显得很怪异,不过习惯了,就会喜欢上括号表示的,特别是Emacs对括号表达式的支持非常好,有一个 par-mode
可以对括号表达式,进行非常快速高效的编辑变换。
上面 Clojure 代码中的的 every? 是接受两个参数,一个函数 f
#(Character/isWhitespace %)
和一个 c
- collection
做为参数,注意,以函数为参数是函数式语言的特性,函数是可以参数传递的。对于collection
中的元素,本例中即是str
,f
作用于 c
的每一个元素,都返回为真的话,那么 every?
也返回为真。
defrecord
records
|
|
records 不可改变,records are immutable,但是可以通过 assoc
或者 merge
从原有的 records 创建新的 records
|
|
record
[1](defrecord Foo [a b c])
(defn make-foo
[& {:keys [a b c] :or {a 5 c 7}}]
(Foo. a b c))
(make-foo :b 6)
(make-foo :b 6 :a 8)
很多时候,maps
和 structs
即可完成大部分工作,可为什么还要使用 record
呢? 这里 有介绍.
records
就是 Java class instances (not Clojure maps),具有更好的性能。
参数的容器是一个向量 []
,而不是列表 ()
|
|
|
|
|
|
dosync
|
|
ref
创建了一个引用,dosync
开启了一个事务,事务能不用Java的锁定机制来更新 可变数据 。事务使用了 (STM, software transactional memory) 来支持并发。
什么是 STM 呢?
Software Transactional Memory (STM) is a concurrency control technique
analogous to database transactions for controlling access to shared
memory in concurrent computing. It is an alternative to lock based synchronization.
STM 通过过 ref
and dosync
来构建。如上面的例子所示。
上面的示例,可能不是特别好,可以看参考 [2] 的银行转账的示例
|
|
在 Java 中的方式:
|
|
Clojure 语法糖访问:
|
|
Clojure 提供了简单的函数用于实现 Java 接口,以及从 Java 基类派生。Clojure 的所有函数都实现了 Callable 和 Runnable 接口,下面使用匿名函数创建 Java 线程:
|
|
[2] http://sw1nn.com/blog/2012/04/11/clojure-stm-what-why-how/
想学 clojure 是因为看到一篇 blog ,在 pc 上支持 600k 的并发,太疯狂了,比 Node.js
的 250k 两倍还多,于是就心痒痒。并且 clojure 是 lisp 的方言,已知对 lisp 很有兴趣,
但是好像它被一些人人视为「玩具」——除非你特别牛,用它是找不到工作的。而clojure和
Java一样,是基于JVM的语言,所以它可以真的投入使用,比如 Storm 就是 clojure 的应用。
clojure 的高并发能力
Mac 下安装lein
在已经有 Java 环境的情况下,安装非常简单:
|
|
然后执行下面的命令,开启 repl
|
|
环境搭建:Emacs+cider [4]
使用 lein 创建一个项目
lein new demo
用 Emacs 打开 demo/src/demo/core.clj,执行 M-x cider-jack-in (或使用快捷键 C-c M-j )开启 nREPL server 以及 Emacs client ,这样就可以在 Emacs 中和后台的 server 交互了
如果出现如下的报错:ider-jack-in can’t find cider-nrepl
添加一个文件 ~/.lein/profiles.clj
|
|
在编辑器中测试代码:在 demo/src/demo/core.clj 里面
注意在执行 (foo “hello”) 之前,要执行前面的两个表达式
在repl中执行代码
使用 lein 在 termial 中执行代码
可以看到,缺少 main 函数,修改下代码
也可以指定为其它的函数为入口函数
project.clj 的所有配置项目见 https://github.com/technomancy/leiningen/blob/stable/sample.project.clj
学习 learning 需要 Java 的经验吗?[1]
使用已经存在的Java API,那必须还是要和Java打交道
You don’t need to write any Java code to use Java APIs from Clojure, but you do need to know enough Java (method signatures, data types etc.) to be able to read the JavaDoc documentation of the APIs and convert this into an appropriate Clojure function call. Often, this is as simple as (.someJavaMethod someJavaObject param1 param2) but sometimes it can be more complex (e.g. when you need to instantiate a subclass of some Java class to pass as a parameter)
clojure 是最终会编译为JVM字节码,所以精通Java,应该是有好处的
在哪里寻找第三方的库?
clojure 的中小项目[2]
甚至有一个 clojure-android 的项目,可以让你在 android 上使用 clojure [6]
但是这时一个 hobby project ,性能很成问题
[1] http://stackoverflow.com/questions/5721496/learning-java-so-i-can-get-at-clojure
[2] http://stackoverflow.com/questions/329221/medium-size-clojure-sample-application
[3] http://dev.clojure.org/display/community/Clojure%2BSuccess%2BStories
[4] https://github.com/clojure-emacs/cider
[5] http://stackoverflow.com/questions/11031886/is-clojure-lockfree-by-using-lockfree-algorithms
[6] http://clojure-android.info/
[7] https://github.com/briancarper/cow-blog
[8] http://github.com/richhickey/clojure-contrib
[9] http://zef.me/2470/building-clojure-projects-with-leiningen