For comprehension returning unexpected type with unused assignation

603 views
Skip to first unread message

Erik Bruchez

unread,
May 24, 2013, 2:42:03 PM5/24/13
to scala-i...@googlegroups.com
All:

With 2.10.1:

scala> for ((k, v) <- Map("a" -> "b")) yield v -> k
res0: scala.collection.immutable.Map[String,String] = Map(b -> a)

scala> for ((k, v) <- Map("a" -> "b"); a = k.length) yield v -> k
res1: scala.collection.immutable.Map[String,String] = Map(b -> a)

But:

scala> for ((k, v) <- Map("a" -> "b"); a = k.length; b = v.length) yield v -> k
res2: scala.collection.immutable.Iterable[(String, String)] = List((b,a))

Am I missing something, or bug?

-Erik

Paul Phillips

unread,
May 24, 2013, 3:37:01 PM5/24/13
to scala-i...@googlegroups.com

On Fri, May 24, 2013 at 11:42 AM, Erik Bruchez <ebru...@gmail.com> wrote:
scala> for ((k, v) <- Map("a" -> "b"); a = k.length; b = v.length) yield v -> k
res2: scala.collection.immutable.Iterable[(String, String)] = List((b,a))

Holy conflation of concerns.

In the translation to map/flatMap/etc the mid-stream assignments are smuggled forward by smashing them into a tuple which accompanies the actual result. The reason you get away with it once is that it goes from a 2-tuple to another 2-tuple - (String, String) to ((String, String), Int). But it doesn't continue nesting them, so next you get a 3-tuple ((String, String), Int, Int) and so the inferencer thinks you are lacking in evidence that you are producing 2-tuples.

There is so much wrong with what I've just described I don't even know what to say, but if you want a workaround, don't let it stack up:

scala> for ((k, v) <- Map("a" -> "b"); a = k.length; _ <- 1 to 1 ; b = v.length) yield v -> k

Erik Bruchez

unread,
May 24, 2013, 3:57:46 PM5/24/13
to scala-i...@googlegroups.com
> In the translation to map/flatMap/etc the mid-stream assignments are
> smuggled forward by smashing them into a tuple which accompanies the actual
> result. The reason you get away with it once is that it goes from a 2-tuple
> to another 2-tuple - (String, String) to ((String, String), Int). But it
> doesn't continue nesting them, so next you get a 3-tuple ((String, String),
> Int, Int) and so the inferencer thinks you are lacking in evidence that you
> are producing 2-tuples.

I had a vague cloudy thing in my mind suggesting an issue along those lines ;)

> There is so much wrong with what I've just described I don't even know what
> to say, but if you want a workaround, don't let it stack up:
>
> scala> for ((k, v) <- Map("a" -> "b"); a = k.length; _ <- 1 to 1 ; b =
> v.length) yield v -> k
> res0: scala.collection.immutable.Map[String,String] = Map(b -> a)

Thanks. I entered an issue:

https://issues.scala-lang.org/browse/SI-7515

-Erik
Reply all
Reply to author
Forward
0 new messages