Как мне создать гетерогенный массив в Scala?
В javascript мы можем сделать:
["a string", 10, {x : 1}, function() {}].push("another value");
Что такое эквивалент Scala?
4 ответа
Массивы в Scala очень однородны. Это потому, что Scala является статически типизированным языком. Если вам действительно нужны псевдогетерогенные функции, вам нужно использовать неизменяемую структуру данных, которая параметризована ковариантно (большинство неизменных структур данных есть). List
это канонический пример, но Vector
тоже вариант. Тогда вы можете сделать что-то вроде этого:
Vector("a string", 10, Map("x" -> 1), ()=>()) + "another value"
Результат будет типа Vector[Any]
, Не очень полезно с точки зрения статической типизации, но все будет там, как и было обещано.
Кстати, "буквальный синтаксис" для массивов в Scala выглядит следующим образом:
Array(1, 2, 3, 4) // => Array[Int] containing [1, 2, 3, 4]
Смотрите также: Больше информации о постоянных векторах
Scala выберет наиболее конкретный тип элемента Array, который может содержать все значения, в этом случае ему нужен наиболее общий тип Any
который является супертипом любого другого типа:
Array("a string", 10, new { val x = 1 }, () => ()) :+ "another value"
Полученный массив будет иметь тип Array[Any]
,
Scala может вскоре получить возможность создания "разнородного" списка: HList в Scala
Лично я, вероятно, использовал бы кортежи, как упоминает herom в комментарии.
scala> ("a string", 10, (1), () => {})
res1: (java.lang.String, Int, Int, () => Unit) = (a string,10,1,<function0>)
Но вы не можете легко присоединиться к таким структурам.
HList, упомянутый ePharaoh, "создан для этого", но я бы, вероятно, остался в стороне от него. Это тяжело на программировании типов и поэтому может нести неожиданные нагрузки (т.е. создавать много классов при компиляции). Просто будь осторожен. HList из вышеперечисленного (нужна библиотека MetaScala) будет (не доказано, так как я не использую MetaScala):
scala> "a string" :: 10 :: (1) :: () => {} :: HNil
Вы можете добавить и т. Д. (Ну, по крайней мере, добавить) к такому списку, и он будет знать типы. Prepending создает новый тип, который имеет старый тип в качестве хвоста.
Тогда есть один подход, еще не упомянутый. Классы (особенно тематические) очень легки в Scala, и вы можете сделать их как однострочные:
scala> case class MyThing( str: String, int: Int, x: Int, f: () => Unit )
defined class MyThing
scala> MyThing( "a string", 10, 1, ()=>{} )
res2: MyThing = MyThing(a string,10,1,<function0>)
Конечно, это не справится и с добавлением.