2011-05-28 2 views
1

Я написал код в scala для разрешения относительных (файлов) путей, см. Код ниже. Я сохраняю пути как списки строк, и когда я вычисляю относительный путь, я использую переменную списка переменных, в которой храню измененные копии списка, на котором я работаю.scala list manipulation: это хорошая скала?

У меня есть ощущение, что это, вероятно, не лучший способ сделать это, или это так? Должен ли я использовать изменяемый список и манипулировать этим? Или я должен использовать только неизменяемые списки, никаких варов вообще и функциональную версию? Как должен быть написан метод «относительный»?

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,'/')); 
    } 
} 
+0

документ, что делают ваши функции, то есть хороший стиль на каждом языке, тогда кто-то может вам помочь –

ответ

5

В общем, петли формы:

var foo = initialFoo 
for (x <- xs) foo = f(foo, x) 

может быть заменен на foldLeft:

val foo = xs.foldLeft(initialFoo)(f) 

В этом конкретном случае версия foldLeft будет выглядеть так:

val list = that.elements.foldLeft(this.elements) { (xs, x) => 
    x match { 
    case "." => xs 
    case ".." => xs init 
    case other => xs :+ other 
    } 
} 

К путь, нет необходимости перебирать список элементов, чтобы скопировать его для начального значения list - это неизменный список, поэтому его можно с уверенностью разделить.

+0

Мне нравится это решение, оно элегантно. Мне кажется, что это «мини-шаблон», который вам нужно изучить, если вы хотите запрограммировать неизменяемые объекты. – Jan

3

Я просто сделаю небольшое изменение для предложения Дэвида; Я обнаружил, что я предпочитаю деконструкции элементы кортежа в foldLeft непосредственно:

val list = that.elements.foldLeft(this.elements) { 
    case (xs, ".") => xs 
    case (xs, "..") => xs init 
    case (xs, x) => xs :+ x 
} 

Теперь, есть здесь головоломка. Это работает и делает это красиво ... но, можете ли вы понять, почему PartialFunction [(List [String], String), List [String]] продвигается до функции2 [List [String], String , List [String]]? :)

+0

Прохладный, я не понимал, что вы можете это сделать. –

+0

Это особенно хорошо для таких вещей, как свертывание карт: Карта («a» -> 1) .foldLeft («») {case (res, (str, i)) => res + ";" + str + ":" + i} –