2014-10-01 55 views
25

requireassert都用於在運行時期間執行某些檢查以驗證某些條件。在scala中require和assert之間做什麼選擇

那麼他們之間的基本區別是什麼?

我看到的唯一一個是require拋出IllegalArgumentExceptionassert拋出AssertionError

如何選擇使用哪一個?

回答

47

由於Kigyo提到的是有語義差別

  • 斷言意味着你的節目已經達到了不一致的狀態,這可能是當前的方法/功能相關的問題(我喜歡把它有點像HTTP 500 InternalServerError)
  • 要求意味着該方法的調用者有過錯,並修補其呼叫(我喜歡把它有點像HTTP 400錯誤請求)

還有一個主要的技術區別:

assert標註有@elidable(ASSERTION) 這意味着你可以用-Xelide-below ASSERTION-Xdisable-assertions編譯程序和編譯器不會生成斷言字節碼。如果您有大量斷言,這可以顯着減少字節碼大小並提高性能。

知道了這一點,你可以用一個assert驗證所有不變量到處在你的程序(每個單獨的方法/函數調用的所有前提條件/後置),並沒有付出代價的生產。

你會通常有「測試」建立並啓用,這將是更慢,因爲這將驗證在任何時候都斷言的所有斷言,那麼你可以有「生產」你的產品的構建沒有斷言,你會消除通過斷言完成的所有內部狀態檢查

require不是可以消除的,它更適合用於庫(包括內部庫)來通知調用者調用給定方法的前提條件/功能。

15

這只是我的主觀觀點。當我想要參數約束時,我使用require

作爲一個例子,我們可以採用自然數的階乘。由於我們不想處理負數,我們想要投出IllegalArgumentException

我會使用assert,只要你想確保一些條件(如不變式)在執行過程中總是爲真。我把它看作是一種測試方式。

這裏是一示例實現階乘與requireassert

def fac(i: Int) = { 
    require(i >= 0, "i must be non negative") //this is for correct input 

    @tailrec def loop(k: Int, result: Long = 1): Long = { 
    assert(result == 1 || result >= k) //this is only for verification 

    if(k > 0) loop(k - 1, result * k) else result 
    } 

    loop(i) 
} 

result > 1時爲真,則該循環被執行至少一次。所以結果必須大於或等於k。這將是一個循環不變。

如果您確定自己的代碼是正確的,則可以刪除assert,但require可以保留。

+0

所以基本上它只是爲了理解目的,沒有其他區別 – Roshan 2014-10-01 12:38:04

+0

當給定的條件不滿足時,它們都拋出異常。這只是例外情況,是的。 – Kigyo 2014-10-01 12:40:57

相關問題