Scala Some, None и мой собственный Default

У нас есть Some, None в Scala, и мне нужен третий с именем Default. Идея заключается в следующем:

  • Некоторые означают, что есть некоторая ценность

  • «Нет» означает отсутствие ценности. Не используйте ценность.

  • По умолчанию (моя индивидуальная вещь) означает, что пользователь хочет, чтобы я применил некоторые встроенные значения по умолчанию.

    Он должен действовать как None (т.е. совместим с Option), и я буду относиться к Default особым образом в своих подпрограммах. Я посмотрел на: Scala: что-то вроде Option (Some, None), но с тремя состояниями: Some, None, Unknown

Я не хочу полностью затенять Some, None моими пользовательскими типами. Я хочу, чтобы пользователь мог их использовать и в определенных случаях применять мои собственные значения по умолчанию.

@Michael Zajac дал несколько вариантов, я думаю, что первый довольно хорош.

Я мог бы встроить Some, None и искусственный, как

case object DefaultParamHere {
    def apply(): Option[String] = {
      Some("Substitute me we default framework value, please")
    }
  }

Спасибо!

так что вариант использования будет:

case class Application(artifact: Artifact,
                              mainClass: Class[_],
                              jvmMemory: Option[Memory] = None,
                              jvmOpts: Option[String] = DefaultParamHere(),
                              applicationConfiguration: List[String] = Nil) extends Stage

person Capacytron    schedule 27.11.2016    source источник
comment
Кто ваши пользователи? Программисты? Почему бы не использовать getOrElse(myDefault)?   -  person Yuval Itzchakov    schedule 27.11.2016
comment
Option запечатан, поэтому вы не можете его продлить. Может быть, вам стоит создать еще один слой, то есть еще один класс-оболочку   -  person Raphael Roth    schedule 27.11.2016
comment
@RaphaelRoth, конечно, не могу и ищу другие подходы.   -  person Capacytron    schedule 27.11.2016
comment
@YuvalItzchakov, что вы имеете в виду под getOrElse? Мои пользователи - разработчики. И они должны сказать мне: используйте мое (пользовательское) значение, не используйте какое-либо значение или сделайте что-нибудь хорошее для меня (пользователь устанавливает значение по умолчанию)   -  person Capacytron    schedule 27.11.2016
comment
У вас может быть метод, принимающий def foo[T](default: T), и использовать его как запасной вариант для вашего Option[T]   -  person Yuval Itzchakov    schedule 27.11.2016


Ответы (1)


На самом деле у вас есть несколько вариантов. Ты мог бы:

Используйте контрольное значение. Например, если вы работаете с Option[Int], Some(-1) может кодировать значение "по умолчанию", но не None. Клиентский код должен знать, что это значение требует специальной обработки, что делает это решение слабым. Его легко реализовать, но сложно для тех, кому нужно использовать код, возвращающий контрольные значения. Я бы не рекомендовал такой подход.

Используйте другой тип, например Option[Either[Default, B]]. В этом решении Some(Right(a)) будет представлять существующее значение, Some(Left(Default)) будет представлять ваш особый случай, а None все равно будет полностью представлять отсутствие данных. Default может быть таким же простым, как объект case, который сигнализирует о том, что вам нужно сделать, или какой-то тип данных, содержащий значения по умолчанию, с которыми, возможно, придется иметь дело программе. На мой взгляд, это лучший вариант (каламбур), поскольку он дает понять, какой именно метод может возвращать при возврате этого типа, и заставляет код иметь дело со случаем Default.

Используйте другой тип, например Option[Option[A]]. Здесь Some(Some(a)) будет представлять существующее значение, Some(None) может представлять ваш особый случай, а None то же самое, что и раньше. Это похоже на предыдущее решение, за исключением того, что не было бы способа закодировать дополнительную информацию в случае по умолчанию, и было бы немного более загадочно относительно того, каким на самом деле был метод, возвращающий этот тип. предназначенный для.

Используйте другой тип, например _ 14_. Как и в предыдущих двух решениях, вы можете закодировать свои три случая с помощью Either3[None, Default, A], где Right3(a), Middle3(Default) и Left3(None) будут соответствующими вариантами. Это снова проясняет, для чего предназначен этот тип, и заставляет клиентский код обрабатывать все три случая. Однако это, вероятно, излишек для того, что вам нужно. Тем не менее, если вы когда-нибудь хотели закодировать больше информации в None случае, Either3 всегда под рукой.

Используйте оболочку. Трудно точно сказать, как это будет выглядеть, не зная больше о вашем сценарии использования, но вы могли бы создать простой класс, который будет обертывать Option и предоставлять желаемое значение по умолчанию.

case class Option3[A](opt: Option[A], default: A) {
  def getOrDefault: A = opt.getOrElse(default)
}

Конечно, это, вероятно, не совсем то, что вам нужно, а что-то в этом роде. Вы также можете обеспечить неявное преобразование из вашей оболочки в Option, которое может заменить значение по умолчанию в None случаях или иным образом, в зависимости от того, что вы действительно хотите.

person Michael Zajac    schedule 27.11.2016
comment
Используйте контрольное значение. - это хорошо. Я могу имитировать эти значения по умолчанию. Я могу делать что-то вроде case Object {def apply = {Some (-1)}}, что, я думаю, хороший компромисс ... Решения кажутся мне слишком сложными. Спасибо за идею! - person Capacytron; 28.11.2016
comment
@Sergey Они кажутся сложными, пока кто-то не забудет, что такое контрольное значение, а затем они вносят ошибки, которые может быть трудно исправить. Это компромисс. - person Michael Zajac; 28.11.2016