Reputation: 1612
I wrote some code in scala to resolve relative (file)paths, see code below. I store the paths as lists of strings, and when I calculate a relative path I use a mutable list variable in which I store modified copies of the list on which I work.
I have a gut feeling that this is probably not the best way of doing it, or is it? Should I use a mutable list and manipulate that? Or should I only use immutable Lists, no vars at all and a functional version? How should the method 'relative' be written?
class PathInfo(e: List[String]) {
val elements=e;
def relative(s : String) :PathInfo= relative(PathInfo.fromString(s));
def relative(that : PathInfo) : PathInfo = {
var list : List[String]=List();
for (item <- elements) {
list = list :+ item;
}
for (item <- that.elements) {
item match {
case "." => ;
case ".." => list = list dropRight(1);
case other => list = list :+ other;
}
}
new PathInfo(list);
}
override def toString : String = {
elements.mkString("/");
}
}
object PathInfo {
def fromString(s : String) : PathInfo={
new PathInfo(List.fromString(s,'/'));
}
}
Upvotes: 1
Views: 1038
Reputation: 4580
I'm just going to make a minor edit to David's suggestion; I've found that I prefer deconstructing the elements of the tuple in the foldLeft directly:
val list = that.elements.foldLeft(this.elements) {
case (xs, ".") => xs
case (xs, "..") => xs init
case (xs, x) => xs :+ x
}
Now, there's a puzzler here. This works, and does so in a lovely fashion... but, can you figure out why a PartialFunction[(List[String], String), List[String]] is being promoted to a Function2[List[String], String, List[String]]? :)
Upvotes: 3
Reputation: 8590
In general, loops of the form:
var foo = initialFoo
for (x <- xs) foo = f(foo, x)
can be replaced with a foldLeft:
val foo = xs.foldLeft(initialFoo)(f)
In this specific case the foldLeft version would look like:
val list = that.elements.foldLeft(this.elements) { (xs, x) =>
x match {
case "." => xs
case ".." => xs init
case other => xs :+ other
}
}
By the way, there's no need to iterate over the elements list to copy it for the initial value of list
- it's an immutable List so it is safe to share.
Upvotes: 5