why #babel/traverse use depth-first traverse - babeljs

traverseNode -> context.visit -> context.visitMultiple/context.visitSingle -> context.visitQueue -> path.visit -> traverseNode
Why not breadth-first traverse? Is it to easily manipulate AST node, and to save more space?

Related

Mutable map with multiple values in Scala

I want to have a map so that:
I can update it -> mutable
I can have multiple values -> old multi map
I.e. I need to have a collection of the form:
k1 -> v1, k1 -> v2, ..., k2 -> v1, k2 -> v2, k2 -> v3, etc.
At the end of the day, what I need is to collect all this information as:
k1 -> Seq(v1,v2), ..., k2 -> Seq(v1,v2,v3)
How can I do this in Scala?
Edit
I tried this in Scastie:
val m = new scala.collection.mutable.Map[Int,Int] with scala.collection.mutable.MultiMap[Int,Int]
m += (1 -> 2)
m += (1 -> 3)
m
But I get:
illegal inheritance;
<$anon: Int => Int with Int => scala.collection.mutable.Set[Int]> inherits different type instances of trait Map:
scala.collection.mutable.Map[Int,scala.collection.mutable.Set[Int]] and scala.collection.mutable.Map[Int,Int]
trait MultiMap in package mutable is deprecated (since 2.13.0): Use a scala.collection.mutable.MultiDict in the scala-collection-contrib module
When people say "avoid using mutable structures" in scala, it especially applies to those, who have to ask questions about how to create a multimap.
I mean, it's really no rocket science:
val foo = mutable.Map[Int, List[Int]]().withDefault(_ => Nil)
foo += 1 -> (1::foo(1))
foo += 1 -> (2::foo(1))
foo += 1 -> foo(1).filterNot(Set)
foo += 1 -> foo(1).tail
tuples.foreach { case (k,v) => foo += k -> (v::foo(k)) }
//etc.
But if you have to ask how to do this, chances are you are going to end up using it wrong (which is very easy with mutable structure). I strongly encourage you to stick with immutable collections (and avoid mutable state in general) until you got enough command of the language to be able to definitively identify situations where mutable is actually the correct solution.
As it was discussed in the comments section, you can proceed with MultiDict from scala-collection-contrlib library. Example:
import scala.collection.mutable
def convert[K, V](iterable: Iterable[(K, V)]): mutable.MultiDict[K, V] = {
iterable.foldLeft(mutable.MultiDict.empty[K, V])(_ addOne _)
}
val list = List("k1" -> "v1", "k1" -> "v2", "k1" -> "v3", "k2" -> "v1", "k3" -> "v1")
val map = convert(list)
println(map.sets)
Will print: HashMap(k1 -> HashSet(v1, v2, v3), k2 -> HashSet(v1), k3 -> HashSet(v1))
Scatie: https://scastie.scala-lang.org/uULFEKUwTVaSHLpJosnXYw

How to get the possible pair combinaisons of values of a hashmap Scala

I have a hashmap as follows :
val hm : HashMap[Int, List[String]] =
HashMap(
1 -> List("Eat", "Drink","Sleep", "work"),
2 -> List("Eat", "Sleep","Dance"),
3 -> List("Write", "Print","Dance")
)
I want to retrieve the possible pairs of this hashmap's values and return each pair separately in a list
I'm using the combinaisons function as
hm.mapValues(_.combinations(2).toList)
The result is :
Map(1-> List(List(Eat, Drink), List(Eat, Sleep), List(Eat, work), List(Drink, Sleep), List(Drink, work), List(Sleep, work)), 2-> List(List(Eat, Sleep), List(Eat, Dance), List(Sleep, Dance)), 3 -> List(List(Write, Print), List(Write, Dance), List(Print, Dance)))
yet the expected result should be three lists
List(List("Eat", "Drink","Sleep", "work"),List("Eat", "Sleep","Dance"))
List( List("Eat", "Drink","Sleep", "work"),List("Write", "Print","Dance"))
List(List("Eat", "Sleep","Dance"), List("Write", "Print","Dance"))
What am I missing
use only values of your map:
hm.values.toList.combinations(2).toList
https://scalafiddle.io/sf/ZGbHC4c/0

scala: create map with keys from map.keys

I have a map, let's say:
m1:Map[String, Int] = Map(a -> 1, b -> 2, c -> 3, d -> 4)
and i now want to create a second map which has the same keys as the existing map and takes 0 as value for each key. So it should look like this:
m2:Map[String, Int] = Map(a -> 0, b -> 0, c -> 0, d -> 0)
I tried a for loop inside the map definition, but it didn't really work. How can I do that?
thanks!
To create a new map consider
m1.keys.map(k => (k,0)).toMap
and using a for comprehension,
for ( (k,v) <- m1 ) yield k -> 0
The approaches above create a new map. This is in contrast with the use of mapValues which creates a view to the original map and keeps the transformation function which is applied to the original map whenever queried. As far as the transformation function is referentially transparent, namely that it is not dependent on a context, this approach is sound. However, when a context the transformation function refers to, changes, the output from querying to the original map may also change. This is prevented with creating a new, transformed map.
You could just mapValues:
val m2 = m1.mapValues((v) -> 0)
EDIT: do read #elm's answer about the reference implications

How to transpose a map with list values in Scala

How can this map of list,
Map (
"a" -> List(1, 2)
)
be transposed to this list of maps primarily using methods from the Scala libraries?
List(
Map("a" -> 1),
Map("a" -> 2)
)
I can code a solution myself but I am more interested in using library functionality so the preferred solution should use the Scala library where possible while remaining compact and moderately legible.
This second example illustrates the required transformation with a map with more than one entry.
From this,
Map (
10 -> List("10a", "10b", "10c"),
29 -> List("29a", "29b", "29c")
)
to this,
List(
Map(
10 -> "10a",
29 -> "29a"),
Map(
10 -> "10b",
29 -> "29b"),
Map(
10 -> "10c",
29 -> "29c")
)
It can be assumed that all values are lists of the same size.
Optionally the solution could handle the case where the values are empty lists but that is not required. If the solution supports empty list values then this input,
Map (
"a" -> List()
)
should result in List().
val m = Map (
10 -> List("10a", "10b", "10c"),
29 -> List("29a", "29b", "29c")
)
m.map{ case (k, vs) =>
vs.map(k -> _)
}.toList.transpose.map(_.toMap)
Note that this also handles your "empty list" case

How to convert Map[String,Seq[String]] to Map[String,String]

I have a Map[String,Seq[String]] and want to basically covert it to a Map[String,String] since I know the sequence will only have one value.
Someone else already mentioned mapValues, but if I were you I would do it like this:
scala> val m = Map(1 -> Seq(1), 2 -> Seq(2))
m: scala.collection.immutable.Map[Int,Seq[Int]] = Map(1 -> List(1), 2 -> List(2))
scala> m.map { case (k,Seq(v)) => (k,v) }
res0: scala.collection.immutable.Map[Int,Int] = Map(1 -> 1, 2 -> 2)
Two reasons:
The mapValues method produces a view of the result Map, meaning that the function will be recomputed every time you access an element. Unless you plan on accessing each element exactly once, or you only plan on accessing a very small percentage of them, you don't want that recomputation to take place.
Using a case with (k,Seq(v)) ensures that an exception will be thrown if the function ever sees a Seq that doesn't contain exactly one element. Using _(0) or _.head will throw an exception if there are zero elements, but will not complain if you had more than one, which will likely result in mysterious bugs later on when things go missing without errors.
You can use mapValues().
scala> Map("a" -> Seq("aaa"), "b" -> Seq("bbb"))
res0: scala.collection.immutable.Map[java.lang.String,Seq[java.lang.String]] = M
ap(a -> List(aaa), b -> List(bbb))
scala> res0.mapValues(_(0))
res1: scala.collection.immutable.Map[java.lang.String,java.lang.String] = Map(a
-> aaa, b -> bbb)
I think I got it by doing the following:
mymap.flatMap(x => Map(x._1 -> x._2.head))
Yet another suggestion:
m mapValues { _.mkString }
This one's agnostic to whether the Seq has multiple elements -- it'll just concatenate all the strings together. If you're concerned about the recomputation of each value, you can make it happen up-front:
(m mapValues { _.mkString }).view.force