В документах для списка указано:

Тип результирующей коллекции определяется статическим типом списка. Иногда это может приводить к неожиданным результатам. Например:

// letterOf вернет Seq [Char] вероятных повторяющихся букв вместо Set def letterOf (words: Seq [String]) = words flatMap (word => word.toSet)

// letterOf вернет Set [Char], а не Seq def letterOf (words: Seq [String]) = words.toSet flatMap (word => word.toSeq)

Мне сложно это понять. StringOps.toSet возвращает Set of Char, поэтому в первом примере возвращается Char Seq - нормально. В этом есть смысл. Я не понимаю, почему во втором примере Scala создает Set вместо Seq.

Что именно здесь означает «результирующая коллекция руководствуется статическим типом списка»?

1
Scala Newb 22 Май 2013 в 23:48

1 ответ

Лучший ответ

Из-за определения метода canBuildFrom в классе Set. Как вы можете видеть в ScalaDoc's CanBuildFrom, у него есть три параметра типа CanBuildFrom[-From, -Elem, +To], где:

От - тип базовой коллекции, которая запрашивает создание построителя.
Elem - тип элемента создаваемой коллекции.
Кому - тип создаваемой коллекции.

Обычно, когда вы вызываете свою функцию flatMap для набора, она неявно вызывает Set.canBuildFrom[Char], которые возвращают Set[Char]

Что касается статического типа. Когда Scala пытается выполнить преобразование между типами коллекций, он использует эту черту CanBuildFrom, которая зависит от статического типа вашей коллекции.

Обновлено для комментария

Если мы добавим -Xprint: typer к команде scala, мы увидим, как компилятор Scala после фазы typer разрешает неявный метод Set.canBuildFrom [Char], который используется в методе flatMap

def lettersOf(words: Seq[String]): scala.collection.immutable.Set[Char] = words.toSet[String].flatMap[Char, scala.collection.immutable.Set[Char]](((word: String) => scala.this.Predef.augmentString(word).toSeq))(immutable.this.Set.canBuildFrom[Char])
1
4lex1v 23 Май 2013 в 18:00
Вот в чем дело - я полностью пропустил вызов toSet во втором примере! Это все проясняет. Дох.
 – 
Scala Newb
23 Май 2013 в 17:59
Я обновил ответ, чтобы показать, когда Scala вводит неявный метод.
 – 
4lex1v
23 Май 2013 в 18:01