开始学习clojure,网上看到的一个快速入门学习的文章,推荐下,转自:https://segmentfault.com/a/1190000000414279
Clojure是运行在JVM上的Lisp家族中的一员。她比Common Lisp更强调纯函数式编程,且自发布时便包含了一组工具来处理状态。
这种组合让她能十分简单且自动地处理并发问题。
(你需要使用Clojure 1.2或更新的发行版)
Clojure代码由一个个form组成, 即写在小括号里的由空格分开的一组语句。
Clojure解释器会把第一个元素当做一个函数或者宏来调用,其余的被认为是参数。
Clojure代码的第一条语句一般是用ns来指定当前的命名空间。
str会使用所有参数来创建一个字符串
数学计算比较直观
等号是 =
逻辑非
嵌套的form工作起来应该和你预想的一样
类型
Clojure使用Java的Object来描述布尔值、字符串和数字
用函数 class 来查看具体的类型
如果你想创建一组数据字面量,用单引号(‘)来阻止form被解析和求值
单引号是quote的简写形式,故上式等价于(quote (+ 1 2))
可以对一个引用列表求值
集合(Collection)和序列
List的底层实现是链表,Vector的底层实现是数组
二者也都是java类
list本可以写成(1 2 3), 但必须用引用来避免被解释器当做函数来求值。
(list 1 2 3)等价于'(1 2 3)
集合其实就是一组数据
List和Vector都是集合:
序列 (seqs) 是数据列表的抽象描述
只有列表才可称作序列。
序列被访问时只需要提供一个值,所以序列可以被惰性加载——也就意味着可以定义一个无限序列:
cons用以向列表或向量的起始位置添加元素
conj将以最高效的方式向集合中添加元素。
对于列表,数据会在起始位置插入,而对于向量,则在末尾位置插入。
用concat来合并列表或向量
用filter来过滤集合中的元素,用map来根据指定的函数来映射得到一个新的集合
recuce使用函数来规约集合
reduce还能指定一个初始参数
函数
用fn来创建函数。函数的返回值是最后一个表达式的值
你需要再嵌套一组小括号来调用它
你可以用def来创建一个变量(var)
将函数定义为一个变量(var)
你可用defn来简化函数的定义
中括号内的内容是函数的参数。
你还可以用这种简写的方式来创建函数:
函数也可以有多个参数列表。
可以定义变参函数,即把&后面的参数全部放入一个序列
可以混用定参和变参(用&来界定)
哈希表
基于hash的map和基于数组的map(即arraymap)实现了相同的接口,hashmap查询起来比较快,
但不保证元素的顺序。
arraymap在足够大的时候,大多数操作会将其自动转换成hashmap,
所以不用担心(对大的arraymap的查询性能)。
map支持很多类型的key,但推荐使用keyword类型
keyword类型和字符串类似,但做了一些优化。
顺便说一下,map里的逗号是可有可无的,作用只是提高map的可读性。
从map中查找元素就像把map名作为函数调用一样。
可以把keyword写在前面来从map中查找元素。
但不要试图用字符串类型的key来这么做。
查找不存在的key会返回nil。
用assoc函数来向hashmap里添加元素
但是要记住的是clojure的数据类型是不可变的!
用dissoc来移除元素
集合(Set)
用conj新增元素
用disj移除元素
把集合当做函数调用来检查元素是否存在:
在clojure.sets模块下有很多相关函数。
常用的form
clojure里的逻辑控制结构都是用宏(macro)实现的,这在语法上看起来没什么不同。
用let来创建临时的绑定变量。
用do将多个语句组合在一起依次执行
函数定义里有一个隐式的do
let也是如此
模块
用use来导入模块里的所有函数
然后就可以使用set相关的函数了
你也可以从一个模块里导入一部分函数。
用require来导入一个模块
用/来调用模块里的函数
下面是从模块clojure.string里调用blank?函数。
在import里你可以给模块名指定一个较短的别名。
#””用来表示一个正则表达式
你可以在一个namespace定义里用:require的方式来require(或use,但最好不要用)模块。
这样的话你无需引用模块列表。
Java
Java有大量的优秀的库,你肯定想学会如何用clojure来使用这些Java库。
用import来导入java类
也可以在ns定义里导入
用类名末尾加.的方式来new一个Java对象
用.操作符来调用方法,或者用.method的简化方式。
用/调用静态方法
用doto来更方便的使用(可变)类。
STM
软件内存事务(Software Transactional Memory)被clojure用来处理持久化的状态。
clojure里内置了一些结构来使用STM。
atom是最简单的。给它传一个初始值
用swap!更新atom。
swap!会以atom的当前值为第一个参数来调用一个指定的函数,
swap其余的参数作为该函数的第二个参数。
用@读取atom的值
下例是一个使用atom实现的简单计数器
其他STM相关的结构是ref和agent.
; Refs: http://clojure.org/refs
; Agents: http://clojure.org/agents
进阶读物
本文肯定不足以讲述关于clojure的一切,但是希望足以让你迈出第一步。
Clojure.org官网有很多文章:
http://clojure.org/
Clojuredocs.org有大多数核心函数的文档,还带了示例哦:
http://clojuredocs.org/quickref/Clojure%20Core
4Clojure是个很赞的用来练习clojure/FP技能的地方:
http://www.4clojure.com/
Clojure-doc.org 有很多入门级的文章:
http://clojure-doc.org/