2.3 函数
在Clojure中,函数调用是一个列表,其第一个元素为函数名。如:
user=> (str "hello" " " "world")
"hello world"
在Clojure中,函数名习惯用连字符(-)连接个部分,如clear-agent-errors。如果一个函数是谓语,那么它的名字习惯性以问号(?)结尾。如:
user=> (string? "hello")
函数定义
定义函数使用defn关键字:
(defn name doc-string? attr-map? [params*] body)
如:
user=> (defn greeting
"Returns a greeting of the form 'Hello, username.'"
[username]
(str "Hello, " username))
#'user/greeting
调用函数greeting:
user=> (greeting "Tom")
"Hello, Tom"
查看函数doc:
user=> (doc greeting)
-------------------------
user/greeting
([username])
Returns a greeting of the form 'Hello, username.'
说明:调用Clojure函数时,传入参数必须与函数定义参数个数一致,否则抛出IllegalArgumentException异常:
user=> (greeting)
java.lang.IllegalArgumentException: Wrong number of args passed to
g (NO_SOURCE_FILE:0)
user=> (greeting "a" "b")
java.lang.IllegalArgumentException: Wrong number of args passed to
g (NO_SOURCE_FILE:0)
多参数形式函数
为了让函数可以适用各种参数情况,可以用定义含多个参数列表和方法体的函数:
(defn name doc-string? attr-map? ([params*] body)+ )
不同参数的方法体可以互相调用。如:
user=> (defn greeting
"Returns a greeting of the form 'Hello, username.'
Default username is 'world'."
([] (greeting "world"))
([username] (str "Hello, " username)))
#'user/greeting
user=> (greeting)
"Hello, world"
可变参数函数
可以创建可变个数参数函数,在函数参数列表中使用&连接最后一个参数;Clojure调用函数时,将剩余的所有参数序列绑定到&连接的参数上。
user=> (defn date [person-1 person-2 & chaperones]
(println person-1 "and" person-2
"went out with" (count chaperones) "chaperones."))
#'user/date
user=> (date "Romeo" "Juliet" "Friar Lawrence" "Nurse")
Romeo and Juliet went out with 2 chaperones.
匿名函数
defn用来定义一级函数,如果想在函数中定义函数,则需要使用匿名函数。
匿名函数用fn形式定义:
(fn [params*] body)
示例:
user=> (use '[clojure.contrib.str-utils :only (re-split)])
nil
user=> (filter (fn [w] (> (count w) 2)) (re-split #"\W+" "A fine day"))
("fine" "day")
还有一种更简洁的匿名函数,使用隐式参数,参数名依次为%1, %2等等。可以用%代替第一个参数,语法如下:
(#body)
示例:
user=> (filter #(> (count %) 2) (re-split #"\W+" "A fine day it is"))
("fine" "day")
可以使用let在函数内给匿名函数命名,如:
user=> (defn indexable-words [text]
(let [indexable-word? (fn [w] (> (count w) 2))]
(filter indexable-word? (re-split #"\W+" text))))
#'user/indexable-words
user=> (indexable-words "a fine day it is")
("fine" "day")
可以动态创建匿名函数
user=> (defn make-greeter [greeting-prefix]
(fn [username] (str greeting-prefix ", " username)))
#'user/make-greeter
每调用依次make-greeter函数就生成一个函数。可以通过def给生成的函数命名:
user=> (def hello-greeting (make-greeter "Hello"))
#'user/hello-greeting
也可以直接调用生成的函数:
user=> ((make-greeter "Howdy") "pardner")
"Howdy, pardner"
在Clojure中,函数调用是一个列表,其第一个元素为函数名。如:
user=> (str "hello" " " "world")
"hello world"
在Clojure中,函数名习惯用连字符(-)连接个部分,如clear-agent-errors。如果一个函数是谓语,那么它的名字习惯性以问号(?)结尾。如:
user=> (string? "hello")
函数定义
定义函数使用defn关键字:
(defn name doc-string? attr-map? [params*] body)
如:
user=> (defn greeting
"Returns a greeting of the form 'Hello, username.'"
[username]
(str "Hello, " username))
#'user/greeting
调用函数greeting:
user=> (greeting "Tom")
"Hello, Tom"
查看函数doc:
user=> (doc greeting)
-------------------------
user/greeting
([username])
Returns a greeting of the form 'Hello, username.'
说明:调用Clojure函数时,传入参数必须与函数定义参数个数一致,否则抛出IllegalArgumentException异常:
user=> (greeting)
java.lang.IllegalArgumentException: Wrong number of args passed to
g (NO_SOURCE_FILE:0)
user=> (greeting "a" "b")
java.lang.IllegalArgumentException: Wrong number of args passed to
g (NO_SOURCE_FILE:0)
多参数形式函数
为了让函数可以适用各种参数情况,可以用定义含多个参数列表和方法体的函数:
(defn name doc-string? attr-map? ([params*] body)+ )
不同参数的方法体可以互相调用。如:
user=> (defn greeting
"Returns a greeting of the form 'Hello, username.'
Default username is 'world'."
([] (greeting "world"))
([username] (str "Hello, " username)))
#'user/greeting
user=> (greeting)
"Hello, world"
可变参数函数
可以创建可变个数参数函数,在函数参数列表中使用&连接最后一个参数;Clojure调用函数时,将剩余的所有参数序列绑定到&连接的参数上。
user=> (defn date [person-1 person-2 & chaperones]
(println person-1 "and" person-2
"went out with" (count chaperones) "chaperones."))
#'user/date
user=> (date "Romeo" "Juliet" "Friar Lawrence" "Nurse")
Romeo and Juliet went out with 2 chaperones.
匿名函数
defn用来定义一级函数,如果想在函数中定义函数,则需要使用匿名函数。
匿名函数用fn形式定义:
(fn [params*] body)
示例:
user=> (use '[clojure.contrib.str-utils :only (re-split)])
nil
user=> (filter (fn [w] (> (count w) 2)) (re-split #"\W+" "A fine day"))
("fine" "day")
还有一种更简洁的匿名函数,使用隐式参数,参数名依次为%1, %2等等。可以用%代替第一个参数,语法如下:
(#body)
示例:
user=> (filter #(> (count %) 2) (re-split #"\W+" "A fine day it is"))
("fine" "day")
可以使用let在函数内给匿名函数命名,如:
user=> (defn indexable-words [text]
(let [indexable-word? (fn [w] (> (count w) 2))]
(filter indexable-word? (re-split #"\W+" text))))
#'user/indexable-words
user=> (indexable-words "a fine day it is")
("fine" "day")
可以动态创建匿名函数
user=> (defn make-greeter [greeting-prefix]
(fn [username] (str greeting-prefix ", " username)))
#'user/make-greeter
每调用依次make-greeter函数就生成一个函数。可以通过def给生成的函数命名:
user=> (def hello-greeting (make-greeter "Hello"))
#'user/hello-greeting
也可以直接调用生成的函数:
user=> ((make-greeter "Howdy") "pardner")
"Howdy, pardner"