类似? 的三元算子:

我试图避免这样的结构:

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

好的,在这个例子中,thenelse分支很简单,但是您可以对复杂的分支进行映像。 我创建了以下内容:

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}

我想编译器需要额外的东西来推断类型。

69296 次浏览

We can combine How to define a ternary operator in Scala which preserves leading tokens? with the answer to Is Option wrapping a value a good pattern? 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?

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.

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

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.

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