I want to use the new java.nio.file.Files.walkFileTree
in Scala. And I was even successful:
class Visitor
extends
java.nio.file.SimpleFileVisitor [java.nio.file.Path]
{
override def visitFile(
File : java.nio.file.Path,
Attrs : java.nio.file.attribute.BasicFileAttributes) : java.nio.file.FileVisitResult =
{
if (! File.toString.contains(".svn"))
{
System.out.println(File);
} // if
java.nio.file.FileVisitResult.CONTINUE;
} // visitFile
} // Visitor
java.nio.file.Files.walkFileTree (Project_Home, new Visitor)
But while this code works fine I feels a bit like carrying Java paradigms into Scala. So a question to the true Scala Gurus: Is there anything I could improve or is this just it?
A Visitor is really a foreach
without the benefit of functions, so let's make a foreach
. The method is static, but it takes as first argument a Path
, so we'll enrich Path
with a foreach
method, which is done with something like this:
import java.nio.file._
import java.nio.file.attribute.BasicFileAttributes
implicit def fromNioPath(path: Path): TraverseFiles = new TraversePath(path)
And everything else is inside the TraversePath
class, which looks somewhat like this:
class TraversePath(path: Path) {
def foreach(f: (Path, BasicFileAttributes) => Unit) {
// ...
}
}
This is enough for you to write this:
ProjectHome foreach ((file, _) => if (!file.toString.contains(".svn")) println(File))
Of course, it won't actually do anything, so let's get it to do something:
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)
}
}
There, now that line will do the same thing as your code did! However, we can improve it further. It happens that foreach
is the only method required of Traversable
, so we can extend that class, and get all the methods of a Scala collection!
The only problem is that a Traversable.foreach
function takes only one argument, and here we are taking two. We can change it into receive a tuple, though. Here's the full code:
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: I have tested none of this code, because I don't have Java 7 installed. There are probably some bugs.
You could make your code a bit more pretty, but at the end of the day it would still look like the plain old visitor pattern.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With