23

Can I "yield" into a Map?

I've tried

val rndTrans = for (s1 <- 0 to nStates;
                    s2 <- 0 to nStates
                        if rnd.nextDouble() < trans_probability)
                            yield (s1 -> s2);

(and with , instead of ->) but I get the error

TestCaseGenerator.scala:42: error: type mismatch;
 found   : Seq.Projection[(Int, Int)]
 required: Map[State,State]
    new LTS(rndTrans, rndLabeling)

I can see why, but I can't see how to solve this :-/

skaffman
  • 398,947
  • 96
  • 818
  • 769
aioobe
  • 413,195
  • 112
  • 811
  • 826

4 Answers4

22
scala> (for(i <- 0 to 10; j <- 0 to 10) yield (i -> j)) toMap
res1: scala.collection.immutable.Map[Int,Int] = Map((0,10), (5,10), (10,10), (1,10), (6,10), (9,10), (2,10), (7,10), (3,10),  (8,10), (4,10))
Vasil Remeniuk
  • 20,519
  • 6
  • 71
  • 81
  • Hmm, probably close to what I'm looking for, but I get: `error: value toMap is not a member of Seq.Projection[(Int, Int)]` – aioobe Nov 18 '10 at 11:03
  • Thats strange. Which version of Scala are you using? – aioobe Nov 18 '10 at 11:04
  • 1
    `Seq.Projection` is deprecated in 2.8; so it should not be the result of a built-in `for` loop. Could you check your version again? (`println(util.Properties.versionString)`) – Debilski Nov 18 '10 at 11:12
  • Yeah. I'm on 2.7 :-( when will the Ubuntu repos be updated to provide 2.8?? Thanks anyway... – aioobe Nov 18 '10 at 11:18
  • @aioobe FWIW, it's fairly easy to get a later version of scala running in Ubuntu without using the Ubuntu repos. You can a) install the package for your favorite IDE, b) install SBT which will automatically download Scala, or c) download the debian package. See http://www.scala-lang.org/node/292#distributions and/or Daniel's answer to this question: http://stackoverflow.com/questions/4161460/bootstrapping-a-web-server-in-scala. – Aaron Novstrup Nov 18 '10 at 20:33
  • Awsome! Thanks! However, I still can't get sbt working. See [my other question](http://stackoverflow.com/questions/4219133/trying-to-run-sbt-on-ubuntu-error-java-lang-noclassdeffounderror-scala-scalao). – aioobe Nov 18 '10 at 20:37
  • @aioobe There's a ticket on Debian about upgrading the Scala package. I hope they do get to it. – Daniel C. Sobral Nov 18 '10 at 23:17
13

An alternate solution in Scala 2.8:

Welcome to Scala version 2.8.1.r23457-b20101106033551 (Java HotSpot(TM) Client VM, Java 1.6.0_22).
Type in expressions to have them evaluated.
Type :help for more information.

scala> import scala.collection.breakOut            
import scala.collection.breakOut

scala> val list: List[(Int,Int)] = (for(i<-0 to 3;j<-0 to 2) yield(i->j))(breakOut)
list: List[(Int, Int)] = List((0,0), (0,1), (0,2), (1,0), (1,1), (1,2), (2,0), (2,1), (2,2), (3,0), (3,1), (3,2))

scala> val map: Map[Int,Int] = (for(i<-0 to 3;j<-0 to 2) yield(i->j))(breakOut)    
map: Map[Int,Int] = Map((0,2), (1,2), (2,2), (3,2))

scala> val set: Set[(Int,Int)] = (for(i<-0 to 3;j<-0 to 2) yield(i->j))(breakOut)
set: Set[(Int, Int)] = Set((2,2), (3,2), (0,1), (1,2), (0,0), (2,0), (3,1), (0,2), (1,1), (2,1), (1,0), (3,0))

scala> 
Eastsun
  • 18,526
  • 6
  • 57
  • 81
  • 7
    +1 for the ever mysterious (but useful!) breakOut. Correct me if I'm wrong, but I think it affords slightly better performance because it provides a builder that allows direct generation of the map (instead of building another collection which is converted afterward). – Nicolas Payette Nov 18 '10 at 21:01
  • 2
    @Zwirb You are correct. And +1 because I didn't know you could use it with for/yield syntax! :-) – Daniel C. Sobral Nov 18 '10 at 23:15
5

Alternative (works on 2.7):

scala> Map((for(i <- 0 to 10; j <- 0 to 10) yield (i -> j)): _*)
res0: scala.collection.immutable.Map[Int,Int] = Map((0,10), (5,10), (10,10), (1,10), (6,10), (9,10), (2,10), (7,10), (3,10), (8,10), (4,10))
aioobe
  • 413,195
  • 112
  • 811
  • 826
missingfaktor
  • 90,905
  • 62
  • 285
  • 365
1
val rndTrans = (
  for {
    s1 <- 0 to nStates
    s2 <- 0 to nStates if rnd.nextDouble() < trans_probability
  } yield s1 -> s2
  ) (collection.breakOut[Any, (Int, Int), Map[Int, Int]])
AlexY
  • 96
  • 3