9.4 WRITING NEW CONTROL STRUCTURES を読んでいて、複数ファイルに対して「ファイルを開いて特定の処理を行う」ことができるはずと思って実装した。Scala でメソッドをメソッドの引数に取るのは HOF(Higher Order Functions) というらしい。 C でいう関数ポインタがさらに高度になったようなイメージを持っている。
「ファイル名を受け取って、開く」までは共通だけれども、開いたファイルに対して実行したいことが異なる場合は 3 番目のメソッドだけ入れ替えればいいので柔軟性に富む。左から右に処理が書かれているのもわかりやすいかもしれない。⊂( ・∀・) 彡
$ cat /tmp/fruits.txt apple banana $ cat /tmp/animals.txt cat dog
@ import scala.io.Source import scala.io.Source @ val files = List("/tmp/fruits.txt", "/tmp/animals.txt") files: List[String] = List("/tmp/fruits.txt", "/tmp/animals.txt") @ val getFileContents = (path: String) => Source.fromFile(path).getLines getFileContents: String => Iterator[String] = ammonite.$sess.cmd2$$$Lambda$2031/1972193961@11a67420 @ def crunchFiles(paths: List[String], f1: String => Iterator[String], f2: String => Unit): Unit = paths.foreach { path => f1(path).foreach { line => f2(line) } } defined function crunchFiles @ def printWithIndent(line: String) = println(s" $line") defined function printWithIndent @ crunchFiles(files, getFileContents, printWithIndent) apple banana cat dog @ def printIfWordContainsCharA(line: String) = if (line.contains("a")) println(line) defined function printIfWordContainsCharA @ crunchFiles(files, getFileContents, printIfWordContainsCharA) apple banana cat @ import java.io.File import java.io.File @ new File("/tmp").listFiles.filter(_.toString.endsWith("txt")) res23: Array[File] = Array(/tmp/animals.txt, /tmp/fruits.txt) @ def crunchFiles(files: Iterator[String], f1: String => Iterator[String], f2: String => Unit): Unit = files.foreach { path => f1(path).foreach { line => f2(line) } } defined function crunchFiles @ val listTextFilesUnderDirectory = (dir: String) => new File(dir).listFiles.filter(_.toString.endsWith("txt")).toList.map(_.toString).toIterator listTextFilesUnderDirectory: String => Iterator[String] = ammonite.$sess.cmd41$$$Lambda$2447/934433293@4f559d04 @ crunchFiles(listTextFilesUnderDirectory("/tmp"), getFileContents, printIfWordContainsCharA) cat apple banana @ def crunchFiles(dir: String, f0: String => Iterator[String], f1: String => Iterator[String], f2: String => Unit): Unit = f0(dir).foreach { path => f1(path).foreach { line => f2(line) } } defined function crunchFiles @ crunchFiles("/tmp", listTextFilesUnderDirectory, getFileContents, printIfWordContainsCharA) cat apple banana