Frage Ternärer Operator?


Ich versuche, Konstrukte wie diese zu vermeiden:

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

Ok, in diesem Beispiel die then und else Zweig ist einfach, aber Sie können komplexe Bilder darstellen. Ich habe folgendes gebaut:

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)
}

Definiert, dass ich das obige einfache Beispiel ersetzen kann mit:

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

Aber wie kann ich das loswerden? s: String =>? Ich möchte so etwas:

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

Ich schätze, der Compiler benötigt das zusätzliche Zeug, um auf Typen zu schließen.


76
2018-02-09 16:20


Ursprung


Antworten:


Wir können kombinieren Wie definiert man einen ternären Operator in Scala, der führende Token erhält? mit der Antwort auf Ist Option ein Wert ein gutes Muster? bekommen

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

Ist das für Ihre Bedürfnisse angemessen?


21
2018-02-09 16:45



Von Tony Morris 'Lambda Blog:

Ich höre diese Frage sehr oft. Ja tut es. Anstatt von c ? p : q, es ist   geschrieben if(c) p else q.

Dies ist möglicherweise nicht vorzuziehen. Vielleicht möchten Sie es mit dem schreiben   gleiche Syntax wie Java. Leider kannst du nicht. Das ist weil : ist kein   gültige Kennung Keine Angst, | ist! Würden Sie sich damit begnügen?

c ? p | q

Dann benötigen Sie den folgenden Code. Beachten Sie den Call-by-Name (=>)   Anmerkungen zu den Argumenten. Diese Bewertungsstrategie ist erforderlich   Schreiben Sie den ternären Operator von Java richtig um. Dies ist in Java nicht möglich   selbst.

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) 
}

Hier ist ein Beispiel mit dem neuen Operator, den wir gerade definiert haben:

object T {   val condition = true

  import Bool._

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

Habe Spaß ;)


104
2018-02-09 19:06



Rex Kerrs Antwort ausgedrückt in Basic Scala:

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

obwohl ich nicht sicher bin, welchen Teil des If-Else-Konstrukts Sie optimieren möchten.


14
2018-02-09 16:52



Da if-else-Konstruktionen in Scala einen Wert zurückgeben, können Sie diesen verwenden

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

Mehr Info: https://alvinalexander.com/scala/scala-if-then-ternary-operator-cookbook-examples


2
2018-02-13 13:53



Da: für sich selbst kein gültiger Operator sein wird, es sei denn, Sie sind damit einverstanden, immer mit Backticks zu entkommen :, könnten Sie mit einem anderen Zeichen gehen, z.B. "|" wie in einer der Antworten oben. Aber wie wäre es mit Elvis mit einem Spitzbart? ::

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

Das wird natürlich auch nicht funktionieren, wenn Sie Werte als Listen haben, da sie :: operator selbst haben.


0
2018-01-25 20:43