Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
878 views
in Technique[技术] by (71.8m points)

scala - Ternary Operator Similar To ?:

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.

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

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


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...