Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Could Scala's “if … else” have been implemented as a library function?

I'm wondering if if … else could have been implemented in Predef with special compiler treatment, in a similar way to what's being done with classOf[A]: the definition is in Predef, the implementation is filled in by the compiler.

Granted, many people would find reassuring to know that an if is always an if, and an else is always an else, no matter the context. However, defining else as a method on the result type of if would remove it from the list of keywords, and allow library designers to define their own else methods. (I know I can use any keyword as an identifier with backticks, but something like `else` just looks awful in code.) Such methods could be useful in cases discusses in situations such as this one, discussed on the mailing list, where people are forced to use otherwise when defining methods that actually should be named else. (Also discussed on SO here and here.)

So:

  • Would such an approach be possible, even in theory, or does it break some fundamental principle in Scala?
  • What would the downsides be?
like image 947
Jean-Philippe Pellet Avatar asked May 26 '11 08:05

Jean-Philippe Pellet


People also ask

What is if else then construct in Scala?

Like many other applications and programming languages, Scala also has a decision making conditional if-else statements. The if statement conditional block is executed if the condition is found to be True, if not then the else conditional block is implemented (only if, else statement is present).

What is the meaning of => in Scala?

=> is syntactic sugar for creating instances of functions. Recall that every function in scala is an instance of a class. For example, the type Int => String , is equivalent to the type Function1[Int,String] i.e. a function that takes an argument of type Int and returns a String .

What is an expression following the if keyword in Scala?

Scala if statement contains an if keyword followed by a boolean expression. If the boolean expression evaluates to true, then the statements inside the if block are executed. If the boolean expression evaluates to false, the statements inside the if block are not executed.


2 Answers

Maybe I don't understand your question, but you can already implement if ... else ... as a library function. Consider this:

class If[A](condition: =>Boolean)(ifBlock: =>A) {
  def els(elseBlock: =>A):A = condition match {
    case true => ifBlock
    case false => elseBlock
  }
}

new If(2==3)(
  println("equal")
) els (
  println("not equal")
)

Of course this doesn't do exactly what if ... else ... does, but with some polishing I think it would. I once implemented a very simple interpreter for a language that had pattern matching built in with if ... else ... being implemented in much the same way I did here.

like image 162
Kim Stebel Avatar answered Oct 02 '22 20:10

Kim Stebel


The short answer is "yes"; branching logic on some predicate can be implemented as a library function.

It's worth pointing out that, as Viktor Klang and others have noted, if/else is essentially folding a boolean. Folding is something we do frequently - sometimes it's clear and explicit, and sometimes not.

// Either#fold is explicit
scala> Left[String, Double]("fail") fold(identity, _ + 1 toString)
res0: java.lang.String = fail

scala> Right[String, Double](4) fold(identity, _ + 1 toString)
res1: java.lang.String = 5.0

Folding an option cannot be done explicitly, but we do it all the time.

// Option has no fold - wont compile!
Some(5) fold(1+, 0)

// .. but the following is equivalent and valid
scala> Some(5) map(1+) getOrElse(0)
res3: Int = 6

Branching logic on a boolean is also a fold, and you can pimp Boolean accordingly. Note the use of by-name parameters to achieve lazy evaluation. Without this feature, such an implementation wouldn't be possible.

// pimped Boolean - evaluates t when true, f when false
class FoldableBoolean(b: Boolean) {
  def fold[A](t: => A, f: => A) =
    if(b) t else f
}

implicit def b2fb(b: Boolean) = new FoldableBoolean(b)

Now we can fold Booleans:

scala> true fold("true!", "false")
res24: java.lang.String = true!

scala> false fold("true!", "false")
res25: java.lang.String = false
like image 38
Chris Avatar answered Oct 02 '22 20:10

Chris