clojure備忘録[clojureの基本的な特殊形式 その3(fn特殊形式)]
fn特殊形式は、関数をデータとして生成して返却します。
表記
(fn [arg0 arg1 ...] & forms)
または
#(form)
1番目が典型的な表記方法です。これを使っておけば間違いありません。
良く見ると、第1引数が普通の括弧でなく、かぎ括弧「[...]」になっています。
少しフライングですが、[...]は「ベクタ」というデータ「型」のリテラル表記になります。
ま、リストの一種で配列みたいなもんだと思ってください。
いくつか後のエントリで、リテラルを持っているデータ型について詳しく説明します。
第2引数が「&」になっています。
この「&」はそれより後ろの引数が「可変長引数」であることを意味します。
実例については次の項で掲載します。
2番目の表記方法もやっている事は同じです。
が、より簡潔な記述になります。
定義したい関数の引数用ベクタが記述されておらず、
いきなり処理コードが記述され始めます。
ではどのように引数を参照するかと言うと、
「%1」「%2」のように「%」をプリフィックスとして、
その後ろに「X番目の引数である」ことを意味する数字を付加して参照することになります。
実例
まずは関数のデータを返却することを見せます。
user=> (fn [a b] (+ a b)) #<user$eval46$fn__47 user$eval46$fn__47@118fa47> user=>
評価直後に表示された、「#
次に、関数データを生成し、直後に引数 2 3 を渡してみます。
user=> ((fn [a b] (+ a b)) 2 3) 5 user=>
今生成した関数が関数として機能し、2 と 3 の加算結果が返却されています。
関数データもデータなので、defで紐付けて後から再利用することが可能です。
def特殊形式を早速使ってみます。
user=> (def func0 (fn [a b] (+ a b))) #'user/func0 user=> func0 #<user$func0 user$func0@141fab6> user=> (func0 3 4) 7 user=>
定義後、付与した名前を使って再利用できています。
しかし、静的な関数を生成する場合は、
defn(内部でdefを使用しているマクロ)を使用することの方が多いため、
こういう形で使用されるケースはあまりお目にかからないかも。
#を使用して生成したケースでも無名関数は機能します。
「%+引数番号」の使い方をご覧ください。
user=> (def func1 #(/ %1 %2)) #'user/func1 user=> func1 #<user$func1 user$func1@2b7db1> user=> (func1 2 3) 2/3 user=> (func1 3 2) 3/2 user=>
fn特殊形式を使った時よりもトークン数が少なくなるので、
map等のシーケンス関数(関数を引数にとるものが多い)の引数として使用されるケースが多いです。