- 函数
- Function Call
- Function Define
- Overloading
- Variable arguments
- Destructuring
- Body
- 匿名函数
函数
Clojure是一门函数式编程语言,function具有非常重要的地位。
Function Call
函数调用很简单,我们已经见过了很多例子:
(+ 1 2 3)(* 1 2 3)
我们也可以将函数返回让外面使用:
user=> ((or + -) 1 2 3)6
如果我们调用了非法的函数,会报错:
user=> (1 2 3)ClassCastException java.lang.Long cannot be cast to clojure.lang.IFn user/eval1491 (form-init7840101683239336203.clj:1)
这里,1并不是一个合法的operator。
Function Define
一个函数,通常由几个部分组成:
- defn
- 函数名称
- 函数说明(可选)
- 参数列表,使用[]封装
- 函数body
一个例子:
user=> (defn fun1#_=> "a function example"#_=> [name]#_=> (str "hello " name))#'user/fun1user=> (fun1 "world")"hello world"user=> (doc fun1)-------------------------user/fun1([name])a function examplenil
Overloading
我们也可以进行函数重载,如下:
user=> (defn func-multi#_=> ([](str "no arg"))#_=> ([name1](str "arg " name1))#_=> ([name1 name2](str "arg " name1 " " name2)))user=> (func-multi)"no arg"user=> (func-multi "1")"arg 1"user=> (func-multi "1" "2")"arg 1 2"
Variable arguments
我们使用&来支持可变参数
user=> (defn func-args#_=> [name & names]#_=> (str name " " (clojure.string/join " " names)))#'user/func-argsuser=> (func-args "a")"a "user=> (func-args "a" "b")"a b"user=> (func-args "a" "b" "c")"a b c"
Destructuring
我们可以在函数参数里面通过特定的name来获取对应的collection的数据,譬如:
user=> (defn f-vec1 [[a]] [a])#'user/f-vec1user=> (f-vec1 [1 2 3])[1]user=> (defn f-vec2 [[a b]] [a b])#'user/f-vec2user=> (f-vec2 [1 2 3])[1 2]
在上面的例子里面,我们的参数是一个vector,然后[a]以及[a b]表示,我们需要获取这个vector里面的第一个以及第二个数据,并且使用变量a,b存储。
我们也可以使用map,譬如:
user=> (defn f-map [{a :a b :b}] [a b])#'user/f-mapuser=> (f-map {:a 1 :b 2})[1 2]user=> (f-map {:a 1 :c 2})[1 nil]
上面这个例子我们可以用:keys来简化,
user=> (defn f-map-2 [{:keys [a b]}] [a b])#'user/f-map-2user=> (f-map-2 {:a 1 :b 2 :c 3})[1 2]
我们可以通过:as来获取原始的map:
user=> (defn f-map-3 [{:keys [a b] :as m}] [a b (:c m)])#'user/f-map-3user=> (f-map-3 {:a 1 :b 2 :c 3})[1 2 3]
Body
Function的body里面可以包括多个form,Clojure会将最后一个form执行的值作为该函数的返回值:
user=> (defn func-body []#_=> (+ 1 2)#_=> (+ 2 3))#'user/func-bodyuser=> (func-body)5
匿名函数
我们可以通过fn来声明一个匿名函数
user=> ((fn [name] (str "hello " name)) "world")"hello world"
我们也可以通过def来给一个匿名函数设置名称:
user=> (def a (fn [name] (str "hello " name)))#'user/auser=> (a "world")"hello world"
当然,我们更加简化匿名函数,如下:
user=> #(str "hello " %)#object[user$eval1584$fn__1585 0x72445715 "user$eval1584$fn__1585@72445715"]user=> (#(str "hello " %) "world")"hello world"
我们使用%来表明匿名函数的参数,如果有多个参数,则使用%1,%2来获取,使用%&来获取可变参数。
user=> (#(str "hello " %) "world")"hello world"user=> (#(str "hello " %1 " " %2) "world" "a ha")"hello world a ha"user=> (#(str "hello " %1 " " (clojure.string/join " " %&)) "world" "ha" "ha")"hello world ha ha"
