Первый список имеет тип List[Double]
из-за расширения литерального типа. Scala видит литералы и отмечает, что, хотя они и относятся к разным типам, их можно унифицировать, расширив некоторые из них. Если бы не было расширения типов, то был бы принят наиболее распространенный суперкласс AnyVal
.
List(1.1 /* Double literal */), 3 /* Int literal */)
Второй список явно List[Int]
, хотя явный вызов Double
приведет к расширению типа литералов.
List(5 /* Int literal */, 7 /* Int literal */)
Теперь важно отметить, что расширение типов происходит во время компиляции. Скомпилированный код не будет содержать Int
3, только Double
3.0. Однако после того, как список был создан, расширить тип невозможно, потому что сохраненные объекты на самом деле разные.
Итак, как только вы соедините два списка, результирующий тип будет суперклассом Double
и Int
. А именно AnyVal
. Однако в результате взаимодействия с Java AnyVal
не может содержать каких-либо полезных методов (таких как числовые операторы).
Мне интересно, что Clojure делает внутри. Преобразует ли он целые числа в двойные числа при конкатенации? Или он хранит все как Object
(как Scala), но имеет более умные математические операторы?
24.05.2010