Vitamon
Vitamon

Reputation: 548

Scala: wrong type inference when mapping Strings?

I'm trying to compile simple helloworld in Scala, and get error "scala: value capitalize is not a member of Char" Why does compiler think that newW is Char?

val dict = Map(
    "hello" -> "olleh",
    "world" -> "dlrow"
  )

def translate(input: String): String = {
  input.split( """\s+""").map(w => dict.getOrElse(w.toLowerCase, w).map(newW => 
    (if (w(0).isUpper) newW.capitalize else newW))
  ).mkString(" ")
}

Upvotes: 1

Views: 972

Answers (2)

Kristian Domagala
Kristian Domagala

Reputation: 3696

The second call to map in translate is mapping across the value returned from dict.getOrElse(...), whose type is String, which can be implicitly treated as an Iterable[Char]. Thus, the compiler is correctly inferring that newW is of type Char and complaining when you try to call capitalize on it. You're probably looking for something along the lines of

def translate(input: String): String = {
  input.split( """\s+""").map(w => {
    val newW = dict.getOrElse(w.toLowerCase, w)
    (if (w(0).isUpper) newW.capitalize else newW)
  }).mkString(" ")
}

Update: By the way, that will fail at runtime if input is an empty string - it needs at least one more check for safety.

Upvotes: 3

Daniel C. Sobral
Daniel C. Sobral

Reputation: 297155

Here's what's happening:

input // is a string
.split( """\s+""") // is an Array[String]
.map(w => // w is a String, for each String in the Array[String]
  dict.getOrElse(w.toLowerCase, w) // is a String (returned by dict.getOrElse)
  .map(newW => // is a Char, for each Char in the String returned by dict.getOrElse

Upvotes: 3

Related Questions