2012-04-20 28 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,它不計算(沒有打印)。