Тернарный Оператор, Подобный:


Я пытаюсь избегать конструкций вида:

val result = this.getClass.getSimpleName
if (result.endsWith("$")) result.init else result

ок, в этом примере then и else ветви просты, но вы можете изображать сложные. Я построил следующее:

object TernaryOp {
  class Ternary[T](t: T) {
    def is[R](bte: BranchThenElse[T,R]) = if (bte.branch(t)) bte.then(t) else bte.elze(t)
  }
  class Branch[T](branch: T => Boolean) {
    def ?[R] (then: T => R) = new BranchThen(branch,then)
  }
  class BranchThen[T,R](val branch: T => Boolean, val then: T => R)
  class Elze[T,R](elze: T => R) {
    def :: (bt: BranchThen[T,R]) = new BranchThenElse(bt.branch,bt.then,elze)
  }
  class BranchThenElse[T,R](val branch: T => Boolean, val then: T => R, val elze: T => R)
  implicit def any2Ternary[T](t: T) = new Ternary(t)
  implicit def fct2Branch[T](branch: T => Boolean) = new Branch(branch)
  implicit def fct2Elze[T,R](elze: T => R) = new Elze(elze)
}

определено, что я могу заменить приведенный выше простой пример:

this.getClass.getSimpleName is {s: String => s.endsWith("$")} ? {s: String => s.init} :: {s: String => s}

но как я могу избавиться от s: String =>? Я хочу что-то вроде этого:

this.getClass.getSimpleName is {_.endsWith("$")} ? {_.init} :: {identity}

Я думаю, компилятор нуждается в дополнительном материале для вывода типов.

5 78

5 ответов:

мы можем объединить Как определить тернарный оператор в Scala, который сохраняет ведущие токены? в ответ является ли опция обертывания значения хорошим шаблоном? и

scala>   "Hi".getClass.getSimpleName |> {x => x.endsWith("$") ? x.init | x}
res0: String = String

scala> List.getClass.getSimpleName |> {x => x.endsWith("$") ? x.init | x}
res1: String = List

это достаточно для ваших нужд?

С Лямбда-Блог Тони Морриса:

Я слышу этот вопрос много. Да, это так. Вместо c ? p : q, это написано if(c) p else q.

это может быть не предпочтительнее. Возможно, вы хотели бы написать его с помощью тот же синтаксис, что и Java. К сожалению, вы не можете. Это потому что : это не a допустимый идентификатор. Не бойся, | есть! Ты бы согласился на это?

c ? p | q

тогда вам понадобится следующий код. Обратите внимание на называю по имени (=>) аннотации к аргументам. Эта стратегия оценки необходима для правильно перепишите тернарный оператор Java. Это не может быть сделано в Java себя.

case class Bool(b: Boolean) {   
  def ?[X](t: => X) = new {
    def |(f: => X) = if(b) t else f   
  } 
}

object Bool {   
  implicit def BooleanBool(b: Boolean) = Bool(b) 
}

вот пример использования нового оператора, который мы только что определили:

object T {   val condition = true

  import Bool._

  // yay!   
  val x = condition ? "yes" | "no"
}

удачи ;)

ответ Рекса Керра выражается в основном Scala:

"Hi".getClass.getSimpleName match {
  case x if x.endsWith("$") => x.init
  case x => x
}

хотя я не уверен, какую часть конструкции if–else вы хотите оптимизировать.

поскольку конструкции if-else в Scala возвращают значение, вы можете использовать это

val a = if (1 < 0) 1 else 2

дополнительная информация: https://alvinalexander.com/scala/scala-if-then-ternary-operator-cookbook-examples

Так как: сам по себе не будет действительным оператором, если вы не в порядке, всегда избегая его с обратными тиками :, вы можете пойти с другим символом, например "|", как в одном из ответов выше. Но как насчет Элвиса с козлиной бородкой ?::

implicit class Question[T](predicate: => Boolean) {
  def ?(left: => T) = predicate -> left
}
implicit class Colon[R](right: => R) {
  def ::[L <% R](pair: (Boolean, L)): R = if (q._1) q._2 else right
}
val x = (5 % 2 == 0) ? 5 :: 4.5

конечно, это снова не будет работать, если Вы значения списки, так как они имеют :: оператор себя.