Reputation: 413
I'm doing a course in Coursera about Scala functional programming. I'm in the 6th week.
I have the following code:
/* define the map of numbers to letters */
val nmem = Map(
'2' -> "ABC", '3' -> "DEF", '4' -> "GHI", '5' -> "JKL",
'6' -> "MNO", '7' -> "PQRS", '8' -> "TUV", '9' -> "WXYZ"
)
/* invert the map to get a map of letters to digits */
val charCode: Map[Char, Char] =
for {
(digit, str) <- nmem
ltr <- str
} yield ltr -> digit
My question is how does the for-comprehension work? nmem
introduces the key (char) and the value (string) into digit and str. And later we have: ltr <- str which I don't know how it works because I don't understand how the program knows that ltr is a char instead of an string.
Thank you in advance.
Upvotes: 1
Views: 89
Reputation: 44908
This for
-comprehension is desugared into
nmem.flatMap { case (digit, str) => str.map { ltr => (ltr, digit) } }
Since nmem
has type Map[Char, String]
, the compiler knows that (digit, str)
must be of type (Char, String)
. Thus, it knows that str
is of type String
. The elements of a String
are of type Char
, thus the type of ltr
is inferred to be Char
.
If you wanted to write down all the gory details of the type inference, you would get something like this:
nmem.flatMap[(Char, Char), Map[Char, Char]]{
case (digit: Char, str: String) =>
str.map[(Char, Char), Seq[(Char, Char)]]{
(ltr: Char) => (ltr, digit)
}
}
Fortunately, this is not necessary, because all those types can be inferred automatically.
Upvotes: 3
Reputation: 724
The syntax item <- collection
is commonly used to iterate through each item in a collection.
A simple example would be:
for(mapping <- map){
println(mapping)
}
In your case, this is essentially a nested for
loop using yield syntax.
By default it will create a List
and accumulate all the items.
Written with a bit more syntax may help:
val charCode : Map[Char,Char] = { // Cast our result to a Map of (Char, Char)
for ((digit, str) <- nmem; // for every key-value pair (Char, String) in nmem
ltr <- str) // for every ltr (Char) in str (String)
yield ltr -> digit // add a new mapping to the map
}
You can check out https://docs.scala-lang.org/../for-comprehensions.html for more details
Upvotes: 0
Reputation: 1154
The first one actually (digit, str) <- nmem
, gets one tuple from Map[String, String], and next one ltr <- str
gets chars from that string.
Upvotes: -1