【问题标题】:What's the difference between Unit and Nothing?Unit 和 Nothing 有什么区别?
【发布时间】:2012-11-24 09:08:39
【问题描述】:

UnitNothing 两种类型都表示一个不返回任何内容的函数。它们有什么区别?

【问题讨论】:

    标签: scala


    【解决方案1】:

    Unit 是一个只有一个值的类型——参见Unit type。另一方面,Nothing 的值不可能 - 请参阅Bottom type

    不返回任何内容的函数必须具有返回类型Unit。如果是Nothing,则该函数无法返回结果。退出函数的唯一方法是通过异常。


    Nothing 以不同的方式使用。它有两个特点:

    1. Nothing 是所有其他类型的子类型(包括 Null)。
    2. 不存在此类型的实例。

    什么时候有用?考虑None

    object None extends Option[Nothing]
    

    因为Option 的类型参数是协变的,而Nothing 是所有事物的子类型,所以Option[Nothing]Option[A] 的每个类型A 的子类型。因此,我们可以为每个A 创建一个对象None,它是Option[A] 的子类型。这是合理的,因为Nothing 无法实例化,所以Option[Nothing] 将始终没有值。同样

    object Nil extends List[Nothing]
    

    Unit 对应于逻辑真,Nothing 对应于Curry-Howard isomorphism 下的逻辑假,我们将类型视为命题,将函数视为证明。

    【讨论】:

      【解决方案2】:

      Unit 表示 (a) 函数具有输入和输出等副作用,(b) 这些副作用是函数的主要目标。当然,即使函数的类型与Unit 不同,函数也会有副作用。

      Nothing 是 Scala 中的一种特殊类型,因为 (a) 它没有值(单位只有一个值 - ()),所以你不能返回 Nothing 类型的值,并且 (b) 它是所有其他类型的子类型。这意味着如果某物的类型为Nothing,则可以使用它来代替任何其他类型(通过子类型化),但不会产生任何结果。这对于处理异常很有用 - throw 表达式的类型为 Nothing,因此它可以在程序中的任何地方使用。

      简单来说,Nothing 表示程序出错或终止,没有任何返回,而Unit 表示有副作用,但执行正常结束,没有结果。

      Programming in Scala 对此有很好的解释。

      【讨论】:

        【解决方案3】:

        在 Petr 的回复中添加一个方面:Nothing 在类型层次结构中起着重要作用。是底型。这意味着它是所有其他类型的子类型,就像 Any 的对立面,它是一切的超类型。你可以找到一个很好的解释here

        【讨论】:

        • @downvoters:当我写这个答案时,Petr 的回复根本没有提到底部类型方面。他是后来才加的。
        【解决方案4】:

        单位

        单位与Java的void相同。 Java 中的 void 是关键字,但 Kotlin 中的 Unit 是对象。

        现在如果一个函数在 Kotlin 中返回 Unit,这意味着它没有返回任何有意义的东西,该函数只是执行一堆代码并返回 执行流程

        什么都没有

        没有什么是完全不同的。您无法将它与 Java 中的任何内容联系起来。 在 java 中没有诸如 Nothing 之类的东西。

        没有什么意味着执行结束。如果一个函数返回 Nothing,则意味着它没有返回任何内容。甚至不是执行流程

        没有什么比得上黑洞,任何进去的东西都出不来,甚至光也没有(光在这里是“执行流”)。在 Unit 的情况下,发出的光最少。

        因此,如果一个函数返回 Nothing,则代码流到此结束,此后编写的任何内容都无法访问

        现在看下面的代码,

        fun main() {
            unitFun()
            println("after unit")
            nothingFun()
            println("after nothing")   //you get warning here saying "unreachable code"
        }
        
        fun nothingFun(): Nothing {
            println("inside nothing")
            throw Exception()
        }
        
        fun unitFun(): Unit {
            println("inside unit")
        }
        

        输出将是

        inside unit
        after unit
        inside nothing
        Exception in thread "main" java.lang.Exception
        

        注意:一写就收到警告

        println("after nothing")     UnReachable Code
        

        而且你知道原因,因为 nothingFun 甚至没有发回执行流程。

        这里要完成的另一件事是,任何返回 Nothing 的函数都必须抛出任何类型的异常。

        原因:如果您编写一些通用语句(并且不抛出异常),那么该函数将匹配返回类型并且我们没有返回 Nothing 的任何内容,这意味着我们没有任何会吸收执行流程并且永远不会返回的东西。一切都返回一些东西,甚至 Unit 也是一些东西。

        现在,可以说 Nothing 是一个类,因此我们可以将其作为对象并返回它本身。唔唔唔唔?一个很大的nohhhh?

        没有一个类有一个构造函数,但它是私有的,所以你甚至不能为它创建一个对象。

        最后一点

        在幕后,Unit在反编译的字节码中被转换为void(small v),而Nothing被转换为Void(capital V)。

        请看下面的代码,

        var user = null               //First
        var user : User? =null        //Second
        

        这里,第二条语句显示,user 为 Nullable-User 类型。 第一条语句的用户是什么类型?

        有什么猜测吗?

        它是 Nullable-Nothing 类型。

        尝试将第一条语句视为

        var user : Nothing? = null
        

        现在幕后发生了什么,

        Void user = (Void)null;              //First
        User user = (User)null;        //Second
        

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2019-11-19
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2011-02-02
          • 1970-01-01
          相关资源
          最近更新 更多