Ternary Operator Similar To ?:

Scala

Scala Problem Overview


I am trying to avoid constructs like this:

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

Ok, in this example the then and else branch are simple, but you can image complex ones. I built the following:

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

Defined that, I can replace the above simple example with:

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

But how can I get rid of the s: String =>? I want something like that:

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

I guess the compiler needs the extra stuff to infer types.

Scala Solutions


Solution 1 - Scala

From Tony Morris' Lambda Blog:

> I hear this question a lot. Yes it does. Instead of c ? p : q, it is > written if(c) p else q. > > This may not be preferable. Perhaps you’d like to write it using the > same syntax as Java. Sadly, you can’t. This is because : is not a > valid identifier. Fear not, | is! Would you settle for this? > > c ? p | q > > Then you’ll need the following code. Notice the call-by-name (=>) > annotations on the arguments. This evaluation strategy is required to > correctly rewrite Java’s ternary operator. This cannot be done in Java > itself. > > 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) > } > > Here is an example using the new operator that we just defined: > > object T { val condition = true > > import Bool._ > > // yay!
> val x = condition ? "yes" | "no" > } > > Have fun ;)

Solution 2 - Scala

We can combine https://stackoverflow.com/questions/2705920 with the answer to https://stackoverflow.com/questions/4889281 to get

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

Is this adequate for your needs?

Solution 3 - Scala

Rex Kerr’s answer expressed in basic Scala:

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

although I’m not sure what part of the if–else construct you want to optimise.

Solution 4 - Scala

Since if-else constructions in Scala return a value, you can use this

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

More info: https://alvinalexander.com/scala/scala-if-then-ternary-operator-cookbook-examples

Solution 5 - Scala

Since : by itself won't be a valid operator unless you are ok with always escaping it with back ticks :, you could go with another character, e.g. "|" as in one of the answers above. But how about elvis with a goatee ?::

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

Of course this again won't work if you values are lists, since they have :: operator themselves.

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionPeter SchmitzView Question on Stackoverflow
Solution 1 - ScalaLandeiView Answer on Stackoverflow
Solution 2 - ScalaRex KerrView Answer on Stackoverflow
Solution 3 - ScalaDebilskiView Answer on Stackoverflow
Solution 4 - ScalaWouterView Answer on Stackoverflow
Solution 5 - ScalaUstaman SangatView Answer on Stackoverflow