clojure中的小细节

1.&可变参数

(defn add [v1 v2 & others] ;;&后面的是可变参数
(+ v1 v2 
(if others ;;判断可变参数列表是否是空,如果不是累加列表中的值,否则返回0
(reduce + 0 others) ;;使用reduce函数计算others的数字之和。
0
)
)
)

2.defn

(defn -name & decls)作用和defn类似,唯一的不同是创建的函数是私有的

3.assoc vs update-in vs assoc-in

说法不一致,详情参考:http://www.bertschneider.de/2011/01/11/Assoc-vs-Update/
assoc,只允许更新数据结构的第一层。处理数据的性能最高,几乎是assoc-in的两倍。
assoc-in 和update-in 可以使用路径表达式改变数据结构的内层。
如果新的值不依赖旧值,assoc-in就可以满足需求,不需要使用update-in;在有依赖关系时,使用update-in

(defrecord Person [fname lname address])
(defrecourd Address [street city state zip])

(def stu (Person. "Stu" "Halloway" (Address. "200 N Mangum" "Durham" "NC" 27707)))
(assoc stu :fname "Stuart")
(upate-in stu [:address :zip] inc)

4.#’ 获得对象本身而不是值

#’x 等价于( var x)

5.recur 将循环值按顺序重新绑定到表达式上

(loop [i 0]
    (when (< i 5)
        (printlin i)
        (recur (inc i )))) ;loop i will take this value

如果递归的层次太深的话, 可能会产生内存不足。一些编程语言用“tail call optimization”(TCO)的技术来解决这个问题。在clojure中避免这个问题的方法是使用loop和recur。
loop/recur组合把一个递归的调用变成一个迭代(迭代与递归,详情看另一篇文章),迭代不需要占用栈空间。loop special form 跟let special form 类似的地方就是它们都会建立一个本地binding,但是同时它也建立一个递归点,这个递归点就是recur的参数里面的那个函数。loop给这些binding 一个初始值。对recur的调用使得程序的控制权返回给loop并给那些本地binding赋了新的值。给recur传递的参数一定要和loop创建的binding个数一样,recur只能出现在loop的最后一行。

6.conj 给集合添加新值

(conj coll x)(conj coll x & xs)
(conj #{1 2 3} 4) ;=>#{1 2 3 4}

7.disj删除集合原有的值

(disj #{1 2 3} 1) ;=>#{2 3}

8.seq? sequential? coll?
(1)如果参数实现了 ISeq 接口,也就是说提供了first,rest,cons方法,则结果为true

(seq? [1 2])
false
(seq? (seq [1 2]))
true

(2)sequential? 实现了Sequential接口时为true,比如list而map不是

(sequential? [])
true
(sequential? {})
false

(3)colls? 如果参数实现了IPersistentCollection,则返回true

(coll? {:a 1})
true
(coll? (java.util.HashMap.))
false

9.直接将set当做函数测试是否包含某值

(#{1 2 3} 1)
;=>1(有就返回原有的值)
(#{1 2 3} 4)
;=>nil (没有返回nil)

10.求交集和并集
;交集
(clojure.set/intersection s1)
(clojure.set/intersection s1 s2)
(clojure.set/intersection s1 s2 & sets)

(clojure.set/intersection #{1 2 3} #{2 3 4})  ;交集
#{1}

;返回一个集合,第一个集合中的元素排除掉剩余集合的元素
(clojure.set/difference s1)
(clojure.set/difference s1 s2)
(clojure.set/difference s1 s2 & sets)

(clojure.set/difference #{1 2} #{2 3})
#{1}
  1. 导入
    ; :only 值导入一个函数子集
(user '[clojure.set :only [intersection])

;使用require导入一个模块

(require 'clojure.string)

;从一个模块中调用函数

(clojure.string/blank? "") ;=>true

;在导入模块的时候自定义名称

(require '[clojure.string :as str])
(str/replace "This is a test." #"[a-o]" str/upper-case)

;可以使用”:require”从一个命名空间中引入模块
;如果使用:require,就没有必要把模块“引”(前面加个单引号)起来了

(ns test
    :require
        [clojure.string :as str]
        [clojure.set :as set])

;使用import类引入java模块

(import java.util.Date)

;也可以从一个命名空间中引入

(ns test
    (:import java.util.Date
            java.util.Calendar))

;类名字加“.”用来创建对象

(Date.)

;使用.来调用方法,或者使用“.方法名”简写的方式

(.(Date.) getTime)
(.getTime (Date.)) ;等价

;使用/来调用静态方法

(System/currentTimeMillis)

你可能感兴趣的:(clojure,clojure)