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

定义函数

defn

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

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

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

  • 无参数函数
(defn hello-world
    (println "Hello,World!"))
  • 单个参数函数

最开始的函数就是这种方式。

  • 多个参数函数

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

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

        (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))))

函数注释
```clojure        
    (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的定义:

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

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

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

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

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

```clojure
    (def minus-func #(- %1 %2))
    (#(/ %2 %1) 3 4)
    (#(apply / %&) 3 5 7)   ;结果为3/5/7  
```
    
----------
####Reference
> [Clojure 学习入门(6)—— 函数定义](http://blog.csdn.net/ithomer/article/details/17225591)
> [Clojure By Example](http://kimh.github.io/clojure-by-example/#defn)