サーチ…
関数の定義
関数は5つのコンポーネントで定義されています。
defn
キーワードを含むヘッダー、関数の名前。
(defn welcome ....)
関数が何をするかを説明し、文書化するオプションのDocstring。
(defn welcome
"Return a welcome message to the world"
...)
角括弧内のパラメータ。
(defn welcome
"Return a welcome message"
[name]
...)
本文は、関数が実行するプロシージャを記述します。
(defn welcome
"Return a welcome message"
[name]
(str "Hello, " name "!"))
それを呼び出す:
=> (welcome "World")
"Hello, World!"
パラメータとアリティ
Clojure関数は、0個以上のパラメータで定義することができます。
(defn welcome
"Without parameters"
[]
"Hello!")
(defn square
"Take one parameter"
[x]
(* x x))
(defn multiplier
"Two parameters"
[x y]
(* x y))
アリティ
関数が取る引数の数。関数はアーリーオーバーロードをサポートしています。つまり、Clojureの関数は複数の引数セットを使用できます。
(defn sum-args
;; 3 arguments
([x y z]
(+ x y z))
;; 2 arguments
([x y]
(+ x y))
;; 1 argument
([x]
(+ x 1)))
アライテスは同じ仕事をする必要はありません、それぞれのアリティは無関係な何かをすることができます:
(defn do-something
;; 2 arguments
([first second]
(str first " " second))
;; 1 argument
([x]
(* x x x)))
バリアント関数の定義
Clojure関数は、その引数リストに記号&を使用して、任意の数の引数をとるように定義することができます。残りの引数はすべてシーケンスとして収集されます。
(defn sum [& args]
(apply + args))
(defn sum-and-multiply [x & args]
(* x (apply + args)))
呼び出し:
=> (sum 1 11 23 42)
77
=> (sum-and-multiply 2 1 2 3) ;; 2*(1+2+3)
12
匿名関数の定義
匿名関数を定義するには、完全な構文と省略形の2つの方法があります。
完全な匿名関数の構文
(fn [x y] (+ x y))
この式は関数として評価されます。 defn
( &
、引数の非構造化など)で定義された関数で使用できる構文であれば、 fn
形式を使用することもできます。 defn
は実際にはただのマクロです(def (fn ...))
。
簡略化された匿名関数の構文
#(+ %1 %2)
これは簡略表記です。簡略表記法を使用すると、引数に明示的に名前を付ける必要はありません。渡された順番に従って%1
、 %2
、 %3
などの名前が割り当てられます。関数に引数が1つしかない場合、その引数はちょうど%
と呼ばれます。
それぞれを使用する場合
簡略表記にはいくつかの制限があります。引数を破棄することはできません。短縮形の匿名関数をネストすることはできません。次のコードはエラーをスローします:
(def f #(map #(+ %1 2) %1))
サポートされている構文
varargsを簡潔な匿名関数で使用することができます。これは完全に正当です。
#(every? even? %&)
引数の数が変化し、それぞれが偶数の場合はtrueを返します。
(#(every? even? %&) 2 4 6 8)
;; true
(#(every? even? %&) 1 2 4 6)
;; false
見かけの矛盾にもかかわらず、次の例のように、名前を含めることによって名前の付いた無名関数を書くことは可能です。これは、関数が自身を呼び出す必要があるだけでなく、スタックトレースにも必要な場合に特に便利です。
(fn addition [& addends] (apply + addends))