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等のシーケンス関数(関数を引数にとるものが多い)の引数として使用されるケースが多いです。