Посетитель действительно foreach
без использования функций, поэтому давайте сделаем foreach
.Метод является статическим, но он принимает в качестве первого аргумента Path
, поэтому мы обогатим Path
методом foreach
, что делается примерно так:
import java.nio.file._
import java.nio.file.attribute.BasicFileAttributes
implicit def fromNioPath(path: Path): TraverseFiles = new TraversePath(path)
И всеelse находится внутри класса TraversePath
, который выглядит примерно так:
class TraversePath(path: Path) {
def foreach(f: (Path, BasicFileAttributes) => Unit) {
// ...
}
}
Этого вам достаточно, чтобы написать это:
ProjectHome foreach ((file, _) => if (!file.toString.contains(".svn")) println(File))
Конечно, на самом деле это не таксделайте что-нибудь, поэтому давайте заставим это сделать что-то:
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)
}
}
Теперь эта строка будет делать то же самое, что и ваш код!Тем не менее, мы можем улучшить его дальше.Бывает, что foreach
- единственный метод, необходимый для Traversable
, поэтому мы можем расширить этот класс и получить все методы коллекции Scala!
Единственная проблема заключается в том, что функция Traversable.foreach
принимаеттолько один аргумент, а здесь мы принимаем два.Мы можем изменить его на получение кортежа.Вот полный код:
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)
}
Отказ от ответственности: я не тестировал ни один из этого кода, потому что у меня не установлена Java 7.Возможно, есть ошибки.