【问题标题】:Quite confused about this code snippet return types with & without =对这个带有 & 不带 = 的代码片段返回类型感到非常困惑
【发布时间】:2013-08-24 11:16:12
【问题描述】:
object A extends App {

def closure1(x:Int) = {
  object O {
   def getX = x
   def add(y:Int) = x+y
  }
  val foo = O
  foo
}

def closure2(x:Int) {
  object O {
   def getX = x
   def add(y:Int) = x+y
  }
  val foo = O
  foo
}

println(closure1(4).getClass)
println(closure2(4).getClass)
}

result:
 $scala A
 class A$O$3$
 void
  1. 为什么返回类型不同?
  2. 我真的不关心返回类型。我想调用 getX 并添加 - 我想做像closure1(4).getX 这样的事情 - 这是非法的。我该怎么做?

【问题讨论】:

    标签: scala closures equals-operator


    【解决方案1】:

    Scala 有一个不返回任何有趣值的代码的简写符号:省略 = 符号。在 Java 中,这将返回 void,即什么都没有;但在 Scala 中,它实际上是 (),这是名为 Unit 的类型的唯一成员。无论哪种方式,它都是一样的:什么都没有或无意义的占位符。

    您想要一个无意义的占位符的原因是,当您编写通用代码时,您宁愿不必以不同的方式处理某些情况。

    无论如何:

    def f(): Unit = println("Hi")
    

    是一个仅显式返回无内容 () 值的函数(这也是 println 返回的值)。简写是

    def f() { println("Hi") }
    

    现在有一个偷偷摸摸的补充,那就是在 Scala 中,与许多 C 派生语言一样,您可以在所做的任何事情中丢弃返回值。当你把它扔掉时,剩下的就是()。 Scala 会在 closure2 上警告您您正在做一些可疑的事情:

    <console>:16: warning: a pure expression does nothing in statement position
    you may be omitting necessary parentheses
             foo
             ^
    defined module A
    

    但仍然会让你这样做(因为历史上预计这会起作用)。

    所以,总结一下:

    def f {}
    

    是一个只返回无内容占位符() 的方法。如果你把它完整地写出来,语法将是

    def f: Unit = {}
    

    当您尝试返回错误类型的值时,它不会抱怨它会丢弃该值并给您输入Unit,但通常会发出警告:

    def f: Unit = 5
    def f { 5 }
    

    (请注意,现在大多数人反对简写形式(现在是 2.10-is-stable),很大程度上是因为在没有明确解释差异的情况下,新用户经常忽略 = 而没有意识到它然后想知道为什么事情不起作用。所以在未来(2.11 或 2.12 弃用?)def f {} 表单可能不起作用。)

    如果你真的想要一个返回值——例如,你想返回你的对象O(顺便说一下,你可以直接这样做,而无需先将它分配给foo),确保你包括=:

    def f = { object O { def g = 5 }; O }
    
    scala> f.g
    res0: Int = 5
    

    (提示:编译器会抱怨你在这里使用了结构类型。你最好使用trait HasG { def g: Int },然后是object O extends HasG;否则Scala实际上使用反射来调用f.g,原因是我从来没有完全能够跟随。)

    【讨论】:

    • 谢谢。我对获取 getX 并添加工作更感兴趣。但是用户Shadowlands回答了那部分(尽管由于某种原因他删除了他的答案!)
    • @kr - 我更明确地将其添加到我的答案中。
    【解决方案2】:

    我认为 Rex 已经解释了原因,您在定义 closure2 时省略了 =,这使 Scala 编译器认为您不想返回任何内容,即使您打算返回 foo

    scala> def closure3(x: Int) {
         |   object O {
         |     def getX = x
         |     def add(y: Int) = x + y
         |   }
         |   val foo = O
         |   foo
         | }
    <console>:17: warning: a pure expression does nothing in statement position; you may be omitting necessary parentheses
             foo
             ^
    closure3: (x: Int)Unit
    

    注意closure3的返回类型是Unit

    scala> def closure4(x: Int) = {
         |   object O {
         |     def getX = x
         |     def add(y: Int) = x + y
         |   }
         |   O
         | }
    closure4: (x: Int)Object{def getX: Int; def add(y: Int): Int}
    
    scala> closure3(2)
    

    closure3(2)什么都不返回,所以你不能调用getX

    scala> closure4(2)
    res10: Object{def getX: Int; def add(y: Int): Int} = O$2$@a4920bc
    

    【讨论】:

      猜你喜欢
      • 2012-10-05
      • 1970-01-01
      • 2017-08-17
      • 1970-01-01
      • 1970-01-01
      • 2018-09-29
      • 2021-08-22
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多