Order of generators in Scala "for comprehension" affects answer -
i'm new scala, , i'm working through scala impatient cay horstmann. going until got comprehension, , came against cryptic passage (section 2.6, advanced loops , comprehensions):
[start quote]
the generated collection compatible first generator.
for (c <- "hello"; <- 0 1) yield (c + i).tochar // yields "hieflmlmop" (i <- 0 1; c <- "hello") yield (c + i).tochar // yields vector('h', 'e', 'l', 'l', 'o', 'i', 'f', 'm', 'm', 'p')
[end quote]
indeed, running in repl, see result of first code snippet has type string, , second code snippet has type scala.collection.immutable.indexedseq[char].
why types differ? think understand second line of code, don't understand why first line doesn't have type scala.collection.immutable.indexedseq[char]. magic happening string rather vector? author mean "compatible first generator"?
both flatmap
, map
trying build object of same type if possible. first example effectively:
"hello".flatmap { c => (0 1).map { => (c + i).tochar } }
since calling string#flatmap
(stringops#flatmap
exact), try build string
, , it's possible because internal collection returns collection of char
s (try remove tochar
, see different).
in second example:
(0 1).flatmap { => "hello".map { c => yield (c + i).tochar }}
it's impossible generate valid range
, range#flatmap
falls vector
.
another interesting example:
map(1 -> 2, 3 -> 4).map(_._1) //> list(1, 3)
normally map#map
try generate map
, since don't have pairs it's impossible, falls list
update
you can use trick if want generate different default (e.g. want generate list of char
s instead):
for { _ <- list(none) // list type doesn't matter c <- "hello" <- 0 1 } yield (c + i).tochar //> list(h, i, e, f, l, m, l, m, o, p)
Comments
Post a Comment