Столкнулся с проблемой непонимания как работает trait Product.
Пример:
List(1,2).productIterator.toList
Возвращает
List[Any] = List(1, List(2))
Покопавшись в документации пока не смог найти ответа на вопрос почему 2-ой элемент возвращается как List(2) а не просто 2.
Спасибо.
Ответ
Для начала объясню что такое List, потом объясню как работает productIterator
И так List - это абстрактный класс, а значит создать его экземпляр нельзя. То что выглядит как List - на самом деле один из его наследников. У класса List два наследника - кейс-класс :: и кейс-объект Nil
Давай посмотрим на их реализацию:
final case class ::[B](override val head: B, private[scala] var tl: List[B]) extends List[B] {
override def tail : List[B] = tl
override def isEmpty: Boolean = false
}
case object Nil extends List[Nothing] {
override def isEmpty = true
override def head: Nothing =
throw new NoSuchElementException("head of empty list")
override def tail: List[Nothing] =
throw new UnsupportedOperationException("tail of empty list")
// Removal of equals method here might lead to an infinite recursion similar to IntMap.equals.
override def equals(that: Any) = that match {
case that1: scala.collection.GenSeq[_] => that1.isEmpty
case _ => false
}
}
То, что Nil - это пустой список, знают многие, поэтому рассмотрим кейс-класс ::. Как видишь у него два поля - head и tl. Заметь что head- это один элемент, а tl - коллекция(List).
Т.е. когда мы пишем
List(1)
на самом деле создается такой кейс-класс:
::(1, Nil)
::(head = 1, tl = Nil)//тоже самое с именованными параметрами
А когда ты создаешь List(1, 2) на самом деле создается такое:
::(1, ::(2, Nil))
::(head = 1, tl = ::(2, Nil)) //тоже самое с именованными параметрами
Обрати внимание на то, что второй параметр имеет тип List, а значит какого бы ты наследника не передал (:: или Nil) - виден он будет как List
Теперь про productIterator, этот метод возвращает итератор на аргументы класса.
В нашем случае у объекта Nil - нету аргументов, а у класса :: есть всего два аргумента - head и tl. Их значения ты и видишь.
P.S. А метод productIterator у них есть - благодаря тому, что они кейс-класс и кейс-объект.
Полезные материалы:
http://www.alessandrolacava.com/blog/scala-case-classes-in-depth/
http://www.scala-lang.org/api/current/scala/collection/immutable/List.html
исходники Scala
Комментариев нет:
Отправить комментарий