2012-04-20 33 views
3

我想知道是否有可能在scala中实现逻辑蕴涵。 例如:在scala中实现蕴涵逻辑运算符

a implies b 

翻译成:

!a || b 

其中ab一些表达式计算结果为Boolean

我最初开始之后,但是这是一种错误的做法

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

,因为它会评估aab无论这个值。当a为真时,正确的解决方案将仅评估b

回答

5

你想使用的通话按姓名参数,相信下面的应该足够了:

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

说明:

你必须通过在b一定的价值,但你不希望出现这种情况表达评估; Scala可以自动将表达式转换为一个函数,该函数不接受任何参数并对表达式求值。如果需要,您的implies运算符然后评估该无限(零参数)函数。

编译器知道它可以执行此转换,因为您提供的类型签名为=> Boolean。这post更详细地解释,但它的标题是一个很好的简要说明:"Automatic Type-Dependent Closure Construction"

Scala的这个特性使人们可以编写控制结构,或许可以像使用其他语言的宏一样编写控制结构。观察它们如何轻松地使用两个按名称参数重新实现一个while循环:一个用于条件,一个用于主体。

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 
    } 
} 
+2

你调用的* nullary函数*在Scala中调用*名称参数*。 – ziggystar 2012-04-20 16:29:19

+1

是的。正如我链接到的Scala网站上的页面所解释的那样,在Scala中通过将表达式自动转换为无函数来实现“所谓的_call-by-name_评估”。我认为描述_how_ Scala实现语言功能比仅仅注意如何使用call-by-name更具有趣味性和教育性。 – ellisbben 2012-04-20 18:13:43

+0

编辑强调这是一个名叫 – ellisbben 2012-04-20 18:24:25

4

您想让b成为必须评估的函数。这种方式只有在实际访问时才会被评估。

您可以通过将其类型更改为=> Boolean来实现,即无需任何输入即可评估为Boolean

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

下面是如何使用它:

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

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

注意,当atrueb评估(印刷 “评估”)。但是,当afalse,它不计算(没有打印)。