Я загрузил «intellij IDEA keybindings», сначала нажав «ctrl + shift + x», а затем выполнив поиск.
после установки, это, кажется, заставляет работать "ctrl + shift + a". Я думаю, что теперь все мои привязки клавиш являются intellij, но это небольшая цена, которую я когда-либо действительно использовал, был "ctrlshift + a"
Вы заметили, что вы хотите, чтобы какие-то классы case моделировали ваши типы данных. На функциональных языках такие вещи называются «абстрактными типами данных», и вы можете прочитать все о том, как Haskell использует их, немного погуглив. Эквивалент Scala для ADT в Haskell использует запечатанные признаки и классы дел.
Давайте рассмотрим переписывание комбинатора синтаксического анализа JSON из стандартной библиотеки Scala или книгу «Программирование в Scala». Вместо использования Map [String, Any] для представления объектов JSON и вместо использования Any для представления произвольных значений JSON он использует абстрактный тип данных JsValue
для представления значений JSON. JsValue
имеет несколько подтипов, представляющих возможные виды значений JSON: JsString
, JsNumber
, JsObject
, JsArray
, JsBoolean
( JsTrue
, JsFalse
), JsNull
.
Манипулирование данными JSON этой формы включает в себя сопоставление с образцом. Поскольку JsValue запечатан, компилятор предупредит вас, если вы не рассмотрели все случаи. Например, код для toJson
, метод, который принимает JsValue
и возвращает String
представление этих значений, выглядит следующим образом:
def toJson(x: JsValue): String = x match {
case JsNull => "null"
case JsBoolean(b) => b.toString
case JsString(s) => "\"" + s + "\""
case JsNumber(n) => n.toString
case JsArray(xs) => xs.map(toJson).mkString("[",", ","]")
case JsObject(m) => m.map{case (key, value) => toJson(key) + " : " + toJson(value)}.mkString("{",", ","}")
}
Сопоставление с образцом оба позволяют нам убедиться, что мы имеем дело с каждым случаем, а также «разворачивают» базовое значение из его JsType. Он предоставляет безопасный для типов способ узнать, что мы обработали каждый случай.
Кроме того, если вы знаете во время компиляции структуру данных JSON, с которыми вы имеете дело, Вы можете сделать что-то действительно крутое, как экстракторы n8han . Очень мощный материал, зацените.
Ну, есть несколько способов приблизиться к этому. Я бы, вероятно, просто использовал Map [String, Any]
, которая должна отлично работать для ваших целей (при условии, что карта из collection.immutable
, а не collection. изменяемый
). Однако, если вы действительно хотите пройти через некоторую боль, можно дать тип для этого:
sealed trait InnerData[+A] {
val value: A
}
case class InnerString(value: String) extends InnerData[String]
case class InnerMap[A, +B](value: Map[A, B]) extends InnerData[Map[A, B]]
case class InnerBoolean(value: Boolean) extends InnerData[Boolean]
Теперь, предполагая, что вы читали поле данных JSON data
в Поле Scala с именем jsData
, вы бы дали этому полю следующий тип:
val jsData: Map[String, Either[Int, InnerData[_]]
Каждый раз, когда вы извлекаете поле из jsData
, вам нужно будет сопоставить шаблон, проверяя, является ли значение имел тип Left [Int]
или Right [InnerData [_]]
(два подтипа Either [Int, InnerData [_]]
) , Когда у вас есть внутренние данные, вы должны сопоставить шаблон с с , чтобы определить, представляет ли он InnerString
, InnerMap
или InnerBoolean
.
Технически, вы все равно должны выполнить такой тип сопоставления с образцом, чтобы использовать данные после извлечения их из JSON. Преимущество правильного подхода заключается в том, что компилятор проверит вас, чтобы убедиться, что вы не упустили никаких возможностей. Недостатком является то, что вы не можете просто пропустить невозможности (например, 'яйца'
, отображающие на Int
). Кроме того, есть некоторые накладные расходы, накладываемые всеми этими объектами-обертками, так что следите за этим.
Обратите внимание, что Scala действительно позволяет вам определять псевдоним типа, который должен сократить количество LoC, необходимое для этого:
JSON используется в качестве примера в разделе «Программирование в Scala», в главе о синтаксическом анализе комбинатора.