Clojure function

今天记录一下Clojure的function.
Functions are first class object in Clojure.

####定义函数

#####defn
最常用的函数定义方式就是使用defn来定义,首先来写个hello world.

1
2
3
4
(defn hello-world
[name]
(println (name " say Hello,World!"))
(hello-world "brucefeng")

函数再控制台上将会输入“brucefeng say Hello,World!”
通常我们在使用函数是基本有一下两种,无参数和有参数的函数,其中有参数的函数又会出现单个参数和多个参数,每种函数只是在写法上有细微的差别。

  • 无参数函数

    1
    2
    (defn hello-world
    (println "Hello,World!"))
  • 单个参数函数
    最开始的函数就是这种方式。

  • 多个参数函数

    1
    2
    3
    4
    (defn hello-world-multiparam
    [firstname familyname]
    (println (str firstname familyname "say Hello World!")))
    (hello-world-multiparam "bruce" "feng")

当多个参数时,在函数内部可以使用1%,2%这种方式来调用第一个,第二个参数,如:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16

(defn hello-world-multiparam
[firstname familyname]
(println (str %1 %2 "say Hello World!")))
(hello-world-multiparam "bruce" "feng")

(defn name doc-string? attr-map? [params*] prepost-map? body)
(defn name doc-string? attr-map? ([params*] prepost-map? body) + attr-map?)

```
- 多个参数函数
可以在参数列表中包含一个&,即可将剩余的参数放入一个序列,绑定到&后面的变量上
```clojure
(defn greeting
([] (greeting "World"))
([userName] (println (str "Hello " userName))))

#####函数注释

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
        (defn hello-world
"this is a comment"
[name]
(println name " say Hello,World!"))
(doc hello-world)
```
#####函数metadata
```clojure
(defn hello-world
"this is a comment"
{:forstudy "yes"
:added 0.1}
[name]
(println name " say Hello,World!"))
(meta (var hello-world))

使用meta就可以查看函数的元数据了。

(meta (var hello-world))      

现在回头来看看defn的定义:

1
2
(defn name doc-string? attr-map? [params*] prepost-map? body)
(defn name doc-string? attr-map? ([params*] prepost-map? body) + attr-map?)

基本上已经涵盖了上面的集中情况。

#####defn-
(defn- name & decls)
defn-与defn功能一致,都是用于定义函数的,defn-定义的函数作用域是私有的,而defn定义的函数是公有的

####匿名函数
匿名函数就是没有名字的函数,在很多情况下,一个功能较为复杂,但是在其他地方的重用度较低,没有必要单独定义函数,这种时候就可以使用匿名函数。

1
2
(fn [] (println "hello,World!"))
(def plus-func (fn [x y] (+ x y)))

匿名函数可以配合def使用,就可以起到defn相同的作用:

1
2
(def plus-func (fn [x y] (+ x y)))
(println (plus-func 1 2))

当然匿名函数最大的作用不是为了和def一起使用取代defn的,在这里使用这种写法只是为了匿名函数的使用形式.
匿名函数的定义除了使用fn的方式,还可以使用#()的形式,%表示唯一的参数,%1、%2 ..依次表示第1、2、..个参数;%&表示所有参数

(def minus-func #(- %1 %2))
(#(/ %2 %1) 3 4)
(#(apply / %&) 3 5 7)   ;结果为3/5/7

####Reference

Clojure 学习入门(6)—— 函数定义
Clojure By Example