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.
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
}
}
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).
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With