Un visitatore è davvero un foreach
senza il vantaggio di funzioni, quindi facciamo un foreach
. Il metodo è statico, ma ci vuole come primo argomento un Path
, quindi dovremo arricchire Path
con un metodo foreach
, che viene fatto con qualcosa di simile:
import java.nio.file._
import java.nio.file.attribute.BasicFileAttributes
implicit def fromNioPath(path: Path): TraverseFiles = new TraversePath(path)
E tutto il resto è all'interno della classe TraversePath
, che sembra un po 'come questo:
class TraversePath(path: Path) {
def foreach(f: (Path, BasicFileAttributes) => Unit) {
// ...
}
}
questo è sufficiente per voi a scrivere questo:
ProjectHome foreach ((file, _) => if (!file.toString.contains(".svn")) println(File))
Naturalmente, non sarà in realtà fare nulla, quindi cerchiamo di arrivare a fare qualcosa:
class TraversePath(path: Path) {
def foreach(f: (Path, BasicFileAttributes) => Unit) {
class Visitor extends SimpleFileVisitor[Path] {
override def visitFile(file: Path, attrs: BasicFileAttributes): FileVisitResult = try {
f(file, attrs)
FileVisitResult.CONTINUE
} catch {
case _ => FileVisitResult.TERMINATE
}
}
Files.walkFileTree(path, new Visitor)
}
}
Ecco, ora che la linea farà la stessa cosa il tuo codice ha fatto! Tuttavia, possiamo migliorarlo ulteriormente. Succede che l'foreach
è l'unico metodo richiesto da Traversable
, quindi possiamo estendere quella classe e ottenere tutti i metodi di una collezione Scala!
L'unico problema è che una funzione Traversable.foreach
accetta un solo argomento e qui ne stiamo prendendo due. Possiamo cambiarlo in ricevere una tupla, però. Ecco il codice completo:
import java.nio.file._
import java.nio.file.attribute.BasicFileAttributes
import scala.collection.Traversable
// Make it extend Traversable
class TraversePath(path: Path) extends Traversable[(Path, BasicFileAttributes)] {
// Make foreach receive a function from Tuple2 to Unit
def foreach(f: ((Path, BasicFileAttributes)) => Unit) {
class Visitor extends SimpleFileVisitor[Path] {
override def visitFile(file: Path, attrs: BasicFileAttributes): FileVisitResult = try {
// Pass a tuple to f
f(file -> attrs)
FileVisitResult.CONTINUE
} catch {
case _ => FileVisitResult.TERMINATE
}
}
Files.walkFileTree(path, new Visitor)
}
}
ProjectHome foreach {
// use case to seamlessly deconstruct the tuple
case (file, _) => if (!file.toString.contains(".svn")) println(File)
}
Disclaimer: Ho testato niente di tutto questo codice, perché non ho Java 7 installato. Ci sono probabilmente alcuni bug.