Scala, нечто среднее между складкой и картой, поддерживающей ленивую оценку

StackOverflow https://stackoverflow.com/questions/19841403

Вопрос

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

val result:List[B] = (myList:List[A]).foldLeft(C -> List.empty[B]){ 
  case ((c, list), a) =>
    ..some function returning something like..
    C -> (B :: list)
} 

Проблема здесь в том, что мне нужно перевернуть весь список, чтобы получить результирующий список. Скажем, я хочу функцию, которая карты Traversableonce [a] Traversableonce [b] и оценивать только членов, как я их называю? Мне кажется, что это довольно общепринятая проблема, поэтому мне интересно, есть ли общий подход к этому. У меня сейчас есть:

implicit class TraversableOnceEx[T](val self : TraversableOnce[T]) extends AnyVal {

   def foldyMappyFunction[A, U](a:A)(func:(A,T) => (A,U)):TraversableOnce[U] = {
     var currentA = a
     self.map { t =>
        val result = func(currentA, t)
        currentA = result._1
        result._2
     }
   } 
}

Что касается функциональной чистоты, вы не смогли запустить ее параллельно, но в остальном это кажется здравым.

Примером будет; Верните мне каждый элемент, и если это первый раз, когда этот элемент появлялся раньше.

val elements:TraversableOnce[E]
val result = elements.mappyFoldyFunction(Set.empty[E]) {
 (s, e) => (s + e) -> (e -> s.contains(e))
}
result:TraversableOnce[(E,Boolean)]
Это было полезно?

Решение

Вы можете использовать государственную монаду. Вот ваш пример, переписанный с помощью Scalaz:

import scalaz._, Scalaz._

def foldyMappy(i: Int) = State[Set[Int], (Int, Boolean)](s => (s + i, (i, s contains(i))))

val r = List(1, 2, 3, 3, 6).traverseS(foldyMappy)(Set.empty[Int])._2

//List((1,false), (2,false), (3,false), (3,true), (6,false))
println(r)

Другие советы

Похоже, тебе нужно Seqview. Анкет Использовать view или же view(from: Int, until: Int) Методы создания нетронутого представления списка.

Я действительно не понимаю ваш пример, так как ваш чек содержит всегда false.

foldLeft отличается. Это приведет к одному значению, агрегируя все элементы списка. Вам явно нужно map (List => List).

В любом случае, отвечая на ваш вопрос о лени: вы должны использовать Stream вместо List. Stream Не оценивает хвост, прежде чем на самом деле называть его.

Поток API

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top