簡體   English   中英

為什么Scala的predef中的require方法允許String作為參數?

[英]Why does Scala's require method in Predef allow a String as argument?

我可以在Scala的Predef類中使用require方法,並將String作為第二個參數,例如

require ("foo" == "bar", "foobar")

首先考慮將require方法作為第二個參數重載為不同的參數。 但事實並非如此。 require方法的簽名(Scala 2.9.1)是:

require(requirement: Boolean, message: ⇒ Any): Unit

為什么上述方法調用可能?

我不完全理解這個問題,但這里有一點解釋。 requirePredef有一個重載版本:

def require(requirement: Boolean) //...
def require(requirement: Boolean, message: => Any) //...

由於message: => Any ,第二個有點令人困惑message: => Any類型。 如果簡單的話可能會更容易:

def require(requirement: Boolean, message: Any) //...

第二個參數當然是一條消息,如果不滿足斷言,則假定將其附加到錯誤消息中。 您可以想象message應該是String類型,但是Any可以簡單地寫:

require(x == 4, x)

如果不等於4則會將xInt類型)的實際值添加到錯誤消息中。 這就是選擇Any的原因 - 允許任意值。

但那么: =>部分? 這稱為名稱調用 ,基本上意味着: 在訪問它時評估此參數。 想象一下以下片段:

require(list.isEmpty, list.size)

在這種情況下,您需要確保list為空 - 如果不是,請將實際list大小添加到錯誤消息中。 但是,對於普通的調用約定,必須在調用方法之前評估list.size部分 - 這可能是浪費的。 通過按名稱約定調用, list.size僅在第一次使用時進行評估 - 當錯誤消息是構造函數(如果需要)時。

在scala具有默認參數之前, Predef存在require方法(在2.8中引入),因此如果您想要給定參數的默認行為,則重載是唯一的選項。 如消息所示,第二個參數可以是任何東西,然后將其用作拋出的IllegalArgumentExceptionmessage (通過調用其toString方法)( 如果它被拋出 - 即如果需求失敗 )。

請注意,參數實際上是按名稱調用的 ; 也就是說,它被聲明為=> Any ,這意味着只有在需求失敗時才會對其進行評估

這會以對象創建的形式造成性能損失,但在消息構造昂貴的情況下(可能需要對數據結構進行一些O(n)訪問)可能會有用。

問題是,為什么String是第二個參數的有效類型,而簽名說它必須是一個函數message: => Any

簽名並沒有這么說。 簽名表示第二個參數的類型為Any ,並且此參數按名稱傳遞

該“按姓名”由前綴指示=>符號,其並不意味着函數-函數始終表示為輸入參數 => 結果類型 ,與Function0() => type

按“值”和“按名稱”查找參數。

答案很簡單:你期待第二個論點

require(boolean: Boolean, message: => Any): Unit

是一個函數任何及問為什么一個String的工作,即使它不是一個函數

分解為:固定String只是一個函數

  1. 沒有任何爭論
  2. 不需要調用()括號
  3. 每次通話都會產生相同的結果

實際上,以下兩個語句在Scala中是等效的:

def x: String = "ABC" // const value, even though 'def' implies a function
val x: String = "ABC"

所以你可能會說String => Any滿足=> Any

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM