Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Implementing implication logical operator in scala

I was wondering if there is any possibility to implement a logical implication in scala. For example:

a implies b

translating into:

!a || b

where a and b are some expressions that evaluate to Boolean.

I initially started with following, but that is a wrong approach

  implicit def extendedBoolean(a : Boolean) = new {
    def implies(b : Boolean) = {
      !a || b
    }
  }

since it will evaluate both a and b regardless the value of a. The correct solution would only evaluate b when a is true.

like image 866
fikovnik Avatar asked Dec 20 '22 22:12

fikovnik


2 Answers

You want to use a call-by-name parameter, I believe the following should suffice:

implicit def extendedBoolean(a : Boolean) = new {
    def implies(b : => Boolean) = {
      !a || b
    }
  }

Explanation:

You must pass some value in for b but you do not want that expression evaluated; Scala can automatically convert the expression into a function that takes no arguments and evaluates to the expression. Your implies operator then evaluates that nullary (zero-argument) function if need be.

The compiler knows that it can do this conversion because of the type signature you have provided, => Boolean. This post explains in better detail, but its title alone is a very good nutshell explanation of what is going on: "Automatic Type-Dependent Closure Construction".

This feature of Scala enables one to write control constructs, perhaps as easily as one might write them using macros in other languages. Observe how easily they reimplement a while loop using two call-by-name parameters: one for the conditional and one for the body.

object TargetTest2 extends Application {
  //type signature not too terribly mysterious
  def whileLoop(cond: => Boolean)(body: => Unit): Unit =
    if (cond) {
      body
      whileLoop(cond)(body)
    }

  //about as easy to use as a plain-old while() loop
  var i = 10
  whileLoop (i > 0) {
    println(i)
    i -= 1
  }
}
like image 138
ellisbben Avatar answered Jan 05 '23 03:01

ellisbben


You want to make b a function that must be evaluated. That way it will only be evaluated if it is actually accessed.

You do this by changing its type to => Boolean, meaning something that evaluates to a Boolean without needing any input.

implicit def extendedBoolean(a: Boolean) = new {
  def implies(b: => Boolean) = {
    !a || b
  }
}

Here's how to use it:

scala> true implies { println("evaluated"); true }
evaluated
res0: Boolean = true

scala> false implies { println("evaluated"); true }
res1: Boolean = true

Notice that when a is true, b is evaluated (printing "evaluated"). But when a is false, it is not evaluated (nothing printed).

like image 22
dhg Avatar answered Jan 05 '23 04:01

dhg