Как вы можете видеть в https://docs.scala -lang.org / tutorials / FAQ / yield.html
Scala «для понимания» - это синтаксический сахар для объединения нескольких операций с foreach, map, flatMap, filter или withFilter. Scala фактически переводит for-expression в вызовы этих методов, поэтому любой класс, предоставляющий их, или их подмножество, можно использовать для понимания.
Итак, ваша for
петля
for (i <- string.indices) {
val ch = string(i)
if(map.contains(ch)) map(ch) += i
else map += (ch -> ListBuffer(i))
}
эквивалентно
string.indices.foreach(i => {
val ch = string(i)
if(map.contains(ch)) map(ch) += i
else map += (ch -> ListBuffer(i))
})
foreach
интерфейс метода
def foreach[U](f: A => U): Unit
map(ch) += i
возвращает ListBuffer
, но map += (ch -> ListBuffer(i))
возвращает Map
. И когда компилятор пытается определить U
в foreach
аргументе f: Int => U
, он получает что-то между ListBuffer
и Map
и не компилирует его.
Кроме того, компилятор не проверяет тип результата выражения if-else, если вы его где-то не используете.
Вы можете исправить свой код, переписав его следующим образом
def group(string: String) = {
val map = mutable.Map[Char, ListBuffer[Int]]()
def update(i: Int): Unit = {
val ch = string(i)
if(map.contains(ch)) map(ch) += i
else map += (ch -> ListBuffer(i))
}
for (i <- string.indices) update(i)
map
}
Но лучше использовать стандартные методы
def group(string: String) = string.toCharArray.zipWithIndex.groupBy(_._1).mapValues(_.map(_._2))