fnとpartialとcomp
clojureでは、高階関数が重要で、特に関数を作り出す構文・関数・マクロをうまく使いこなせば、短く明瞭なプログラムを書くことができる。
Clojureにおいては、関数を作り出し適用するための仕組みとしてfn, #(), partial, compがある。これらの操作についてまとめてみる。
fnと#()
一番基本となるのがfnおよび#()だ。SchemeやCommon Lispにおけるlambda,つまり無名関数を作り出す。fn と #() は同じ意味だ。
user> (filter #(zero? (rem % 3)) (range 30)) (0 3 6 9 12 15 18 21 24 27) user> (filter (fn [n] (zero? (rem n 3))) (range 30)) (0 3 6 9 12 15 18 21 24 27)
partial
関数の部分適用のためのpartial関数がある。これを使うと、Haskellの部分適用と同じことができる。
user> (map (partial * 3) (range 10)) (0 3 6 9 12 15 18 21 24 27)
つまり (* 3 _) という形の式を考え、 _ の部分を引数として取る1引数の関数が生成される。#(* 3 %) と同じ意味だがより簡潔に書くことができる。
comp
次にcomp。compはcompositionの略、つまり関数合成だ。Haskellでいう "." (ドット)に相当する(たぶん)。次の式は、(range 10)のそれぞれの値から1を引いて2倍し、文字列として返す。
user> (map (comp str (partial * 2) dec) (range 10)) ("-2" "0" "2" "4" "6" "8" "10" "12" "14" "16")
(comp str (partial * 2) dec) までが1つの関数を表す。