对这个带有 & 不带 = 的代码片段返回类型感到非常困惑
Posted
技术标签:
【中文标题】对这个带有 & 不带 = 的代码片段返回类型感到非常困惑【英文标题】: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
-
为什么返回类型不同?
我真的不关心返回类型。我想调用 getX 并添加 - 我想做像closure1(4).getX 这样的事情 - 这是非法的。我该怎么做?
【问题讨论】:
【参考方案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)Objectdef getX: Int; def add(y: Int): Int
scala> closure3(2)
closure3(2)
什么都不返回,所以你不能调用getX
scala> closure4(2)
res10: Objectdef getX: Int; def add(y: Int): Int = O$2$@a4920bc
【讨论】:
以上是关于对这个带有 & 不带 = 的代码片段返回类型感到非常困惑的主要内容,如果未能解决你的问题,请参考以下文章
终于懂了:Delphi重定义消息结构随心所欲,只需要前4个字节是消息编号就行了,跟Windows消息虽然尽量保持一致,但其实相互没有特别大的关系。有了这个,就有了主动,带不带句柄完全看需要。(代码片段
为啥我的 C 代码片段不起作用?简化版可以。为 unsigned long long 传递不带 VA_ARGS 的 args