[英]In Scala, why can I use `Unit` as return type here?
代碼如下:
scala> def f(x:Int => Unit):Unit = 1
<console>:7: warning: a pure expression does nothing in statement position; you may be omitting necessary parentheses
def f(x:Int => Unit):Unit = 1
^
f: (x: Int => Unit)Unit
scala> f(_=>2);
<console>:9: warning: a pure expression does nothing in statement position; you may be omitting necessary parentheses
f(_=>2);
^
scala> f(_=>List(1,2));
上面的所有三個表達式都在REPL中工作(有一些警告),但它們看起來有點令人困惑。
在第一個表達式中, f
的返回類型是Unit
,它是AnyVal
的子類型,但不是Int
的超類型,因此,我無法理解為什么1
可以用作返回值。
在第二個表達式中, _=>2
也使用2
而不是Unit
作為返回值,它與定義沖突。
在第三個表達式中, _=> List(1,2)
甚至使用List
, AnyRef
子類型作為返回值,但REPL仍然沒有抱怨這個..
有沒有人有關於為什么Unit
可以容忍非子類型轉換的想法? 謝謝!
在這種情況下,Scala會自動插入()
(單例Unit
值)以使類型檢查工作。 所以你所擁有的相當於:
def f(x:Int => Unit):Unit = { 1; () }
這在Scala中被稱為“價值丟棄”。 從規格 :
價值丟棄
如果
e
具有某種值類型且預期類型為Unit
,則通過將{ e; () }
嵌入到術語{ e; () }
來將e
轉換為期望類型{ e; () }
{ e; () }
與許多編程語言一樣,這意味着只是“拋棄”表達式的返回值。 這允許您創建一個僅使用表達式副作用的Unit
類型的方法。
檢查SLS中的隱式轉換部分
ValueDiscarding。 如果e具有某種值類型且預期類型為Unit,則通過將e嵌入到術語{e;中來將e轉換為期望類型。 ()}。
除了Ben Reich的答案:
從概念上講,在Scala中,類型Unit
是每種其他類型的超類型。 因此,每個值(包括Int
)都可以分配給Unit
。 實際上,如果用作方法的返回類型,編譯器將丟棄結果值,為方法提供JVM / Java void
類型。
順便說一下, Nothing
是完全相反的:從概念上講,它是所有其他類型的子類型。 由於不存在任何Nothing
實例,因此任何其他類型的實例都不能與Nothing
分配兼容。
Java的void
某種程度上是兩者的不完全混合。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.