Scala Map.mapValues ​​stackoverflowerror

The following code raises a StackOverflowError on the last line.

object StackTest extends App{ @tailrec def incrementValues(acc: Map[String, Int], inc: Int): Map[String, Int] = { if(inc == 0) acc else incrementValues(acc.mapValues(_ + 1), inc - 1) } val myMap = incrementValues(Map("key" -> 0), 10000) myMap.foreach(println) } 

In Scala 2.11.2:

 Exception in thread "main" java.lang.StackOverflowError at scala.collection.MapLike$MappedValues.foreach(MapLike.scala:245) at scala.collection.TraversableLike$WithFilter.foreach(TraversableLike.scala:777) at scala.collection.MapLike$MappedValues.foreach(MapLike.scala:245) at scala.collection.TraversableLike$WithFilter.foreach(TraversableLike.scala:777) at scala.collection.MapLike$MappedValues.foreach(MapLike.scala:245) ... 

Looking at the source for MapLike, I see it using the MappedValues ​​object, which looks like a view:

  protected class MappedValues[C](f: B => C) extends AbstractMap[A, C] with DefaultMap[A, C] { override def foreach[D](g: ((A, C)) => D): Unit = for ((k, v) <- self) g((k, f(v))) def iterator = for ((k, v) <- self.iterator) yield (k, f(v)) override def size = self.size override def contains(key: A) = self.contains(key) def get(key: A) = self.get(key).map(f) } /** Transforms this map by applying a function to every retrieved value. * @param f the function used to transform values of this map. * @return a map view which maps every key of this map * to `f(this(key))`. The resulting map wraps the original map without copying any elements. */ def mapValues[C](f: B => C): Map[A, C] = new MappedValues(f) 

What is the best way to do this to actually match values?

+5
source share
1 answer

mapValues is known to be a trap because it really only creates a package view function, rather than looking forward to creating a new collection. Therefore, in your example, you create a data structure of a nesting level of 10,000.

You can use the usual map method:

 acc.map(tup => (tup._1, tup._2 + 1)) 

or

 acc.map { case (key, value) => (key, value + 1) } 
+7
source

Source: https://habr.com/ru/post/1200936/


All Articles