Clojure China

identity这个函数有什么意义?或者说有什么使用场景

#1

Returns its argument.

4clojure上的文档,但是这有什么用呢?

#2

例如计算一系列数字中每个数字出现的次数,并需要去掉 nil,可以用 identity 来过滤和分组:

(->> [1 0 1 nil 1 nil]
     (filter identity)
     (group-by identity)
     (map (fn [[x xs]] [x (count xs)]))
     (into {}))

;; {1 3, 0 1}

identity 可以用来过滤一个序列里是 nilfalse 的元素(参见 clojuredocs):

(filter identity [1 2 3 nil 4 false true 1234])

;; (1 2 3 4 true 1234)

总之需要用到 (fn [x] x) 的地方就是使用 identity 的时机。
再来一个临时拼凑的例子:

(def ^:dynamic *my-converter*)

(defn hello-world []
  (println "hello" (*my-converter* "world")))

(binding [*my-converter* (fn [x] (str "<" x ">"))]
  (hello-world))
;; hello <world>

(binding [*my-converter* identity]
  (hello-world))
;; hello world
#3

Haskell 也有, 总觉得是做证明的时候用到的.

#4

和 y = x 这个函数在数学中的地位一样。

#5

identity函数的类型是 identity :: T -> T,也即一个类型到同一个类型的转换,也即EndoFunction(自函数)
你可以理解为它把普通类型T提升到一个函数类型 T => T -> T。
这里有个很好的例子:

(sort-by identity [2 3 1 4])
;; (1 2 3 4)

(sort-by keyfn coll)中的keyfn本意是抽取集合中的项的key值来进行比较的,这里我们仅仅需要项来比较。

高阶函数(HOF)需要filter或者抽取原集合的项的类型来做其他操作的时候,那么就可以使用identity来提升普通类型到函数类型。

2赞
#6

还有一种使用情况,就是在destructure 的时候如果有些参数为空的情况,函数内又需要调用。可以通过identity 将空参转变为空函数以防止空指针。 不知道我理解的对不对