"Преобразовать" вариант [x] в x в Scala
Я работаю с воспроизведением для scala (2.1), и мне нужно преобразовать значение "Option [Long]" в "Long".
Я знаю, как делать обратное, я имею в виду:
def toOption[Long](value: Long): Option[Long] = if (value == null) None else Some(value)
Но в моем случае мне нужно передать значение "Option [Long]" как тип в метод, который принимает "Long".
Любая помощь пожалуйста.
Ответы
Ответ 1
Во-первых, ваша реализация "противоположного" имеет некоторые серьезные проблемы. Поместив параметр типа с именем Long
на метод, который вы затеняете тип Long
из стандартной библиотеки. Вероятно, вы имеете в виду следующее:
def toOption(value: Long): Option[Long] =
if (value == null) None else Some(value)
Даже это немного бессмысленно (поскольку scala.Long
не является ссылочным типом и никогда не может быть null
), если вы не ссылаетесь на java.lang.Long
, который является рецептом боли и путаницы. Наконец, даже если вы имеете дело с ссылочным типом (например, String
), вам лучше написать следующее, что в точности эквивалентно:
def toOption(value: String): Option[String] = Option(value)
Этот метод вернет None
тогда и только тогда, когда value
равен null
.
Чтобы решить ваш вопрос, предположим, что мы имеем следующий метод:
def foo(x: Long) = x * 2
Вы не должны, как правило, думать о том, чтобы передать Option[Long]
в foo
, а скорее "поднять" foo
в Option
через map
:
scala> val x: Option[Long] = Some(100L)
x: Option[Long] = Some(100)
scala> x map foo
res14: Option[Long] = Some(200)
Вся точка Option
заключается в моделировании (на уровне типа) возможности "нулевого" значения, чтобы избежать целого класса проблем NullPointerException
-y. Использование map
на Option
позволяет выполнять вычисления по значению, которое может находиться в Option
, продолжая моделировать возможность его пуста.
В качестве еще одного ответа можно также использовать getOrElse
для "освобождения" от Option
, но это обычно не является идиоматическим подходом в Scala (за исключением случаев, когда действительно существует разумное значение по умолчанию).
Ответ 2
Если у вас есть x в качестве опции [Long], x.get
даст вам Long.
Ответ 3
Этот метод уже определен в опции [A] и называется get:
scala> val x = Some(99L)
x: Some[Long] = Some(99)
scala> x.get
res0: Long = 99
Проблема в том, что вызов get на None будет вызывать исключение NoSucheElement:
scala> None.get
java.util.NoSuchElementException: None.get
таким образом вы не получите каких-либо преимуществ от использования типа Option.
Таким образом, как указано выше, вы можете использовать getOrElse, если вы можете предоставить разумное значение по умолчанию или обработать исключение.
Идиоматический способ scala будет использовать карту или понимание для понимания
x map (_ + 1)
res2: Option[Long] = Some(100)
или
for (i <- x) yield i +1
res3: Option[Long] = Some(100)
Ответ 4
Опция - способ локализовать побочный эффект (ваша функция может вернуть пустое значение). И хороший стиль, чтобы поднять ваши вычисления на Option (опция - Monad с картой и методами FlatMap).
val x = Option[Long](10)
x.map { a => a + 10 }
И извлеките значение с ручной обработкой побочного эффекта:
val res = x match {
case Some(a) => s"Value: $a"
case None => "no value"
}
Ответ 5
Вам нужно решить, что произойдет, если опция None
. Предоставляете ли вы значение по умолчанию?
def unroll(opt: Option[Long]): Long = opt getOrElse -1L // -1 if undefined
unroll(None) // -> -1
Вы также можете создать исключение:
def unroll(opt: Option[Long]): Long = opt.getOrElse(throw
new IllegalArgumentException("The option is expected to be defined at this point")
)
unroll(None) // -> exception
В случае, воздержитесь от использования null
, если у вас нет оснований для его использования (opt.orNull
).
Ответ 6
Как уже упоминалось, getOrElse - это то, что вы ищете, отвечая на свой вопрос напрямую.
Обратите внимание, что для преобразования в параметр вы можете просто:
val myOption = Option(1)
myOption теперь будет Some (1)
val myOption = Option(null)
myOption теперь будет None.