たとえば、カレントディレクトリにある 拡張子 .png を持ったファイル名のみのリストを作成したい場合。
kotlin では以下のように書ける。
import java.io.File
val list = File(".").listFiles().filter( { it.name.endsWith(".png") } ).map( {it.name} )
次に png ではなく jpg を列挙したい場合...
import java.io.File
val list = File(".").listFiles().filter( { it.name.endsWith(".jpg") } ).map( {it.name} )
と書けばいいのだが、次に bmp の場合は・・・となるとこのフィルタ実装部分だけを切り離したくなる。
もし Groovy ならば以下のようになる。
def pngFilter = { it.name.endsWith(".png") }
def jpgFilter = { it.name.endsWith(".jpg") }
def bmpFilter = { it.name.endsWith(".bmp") }
def list = new File(".").listFiles().findAll( pngFilter ).collect( {it.name} )
kotlin も同じノリで実装してみると・・・
val pngFilter = { it.name.endsWith(".png") }
val list = File(".").listFiles().filter( pngFilter ).map( {it.name} )
コンパイラに怒られる。
error: type inference failed: inline fun <T> kotlin.Array<out T>.filter(predicate: (T) -> kotlin.Boolean): kotlin.collections.List<T>
どうやら predicate: (T) -> kotlin.Boolean
という関数型がくることを期待しているよ、ということらしい。
(T)
の部分は、今の文脈では File がくるところなので、File に置き換えて、pngFilter に型を明示的に指定するコードに修正。
//val pngFilter:(predicate:File)->kotlin.Boolean = { it.name.endsWith(".png") }
val pngFilter:(File)->kotlin.Boolean = { it.name.endsWith(".png") }
val list = File(".").listFiles().filter( pngFilter ).map( {it.name} )
これで意図通り作動するようになった。