#scala
Столкнулся с проблемой непонимания как работает trait Product. Пример: List(1,2).productIterator.toList Возвращает List[Any] = List(1, List(2)) Покопавшись в документации пока не смог найти ответа на вопрос почему 2-ой элемент возвращается как List(2) а не просто 2. Спасибо.
Ответы
Ответ 1
Для начала объясню что такое 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
Комментариев нет:
Отправить комментарий