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
- Why are the return types different ?
- I really don't care about the return types. I want to call getX and add - I want to do something like closure1(4).getX - this is illegal. How do I do that ?
Scala has a shorthand notation for code that doesn't return any interesting value: omit the
=
sign. In Java, this would returnvoid
, i.e. nothing at all; but in Scala it's actually()
, the only member of the type calledUnit
. Either way, it's the same: nothing or a meaningless placeholder.The reason you want a meaningless placeholder is that when you write generic code you'd rather not have to handle the cases of something vs. nothing differently.
Anyway:
is a function that explicitly returns only the content-free
()
value (which is whatprintln
returns also). And the shorthand isNow there's one sneaky addition which is that in Scala, as with many C-derived languages, you're allowed to just throw away the return value from whatever you do. And when you throw it away, all that's left is
()
. Scala will warn you onclosure2
that you are doing something suspicious:but will still let you do it (as it is historically expected that this will work).
So, to summarize:
is a method that returns only the content-free placeholder
()
. If you write it out in full the syntax would beand when you try to return a value of the wrong type, instead of complaining it throws away the value and gives you type
Unit
, but typically emits a warning:(Note that opinion is mostly against the short form these days (these days being 2.10-is-stable), in large part because in the absence of a clear explanation of the difference, new users often omit
=
without realizing it and then wonder why things don't work. So in the future (2.11 or 2.12 for deprecation?) thedef f {}
form may not work.)If you actually want a return value--because, for example, you want to return your object
O
(which you can do directly without first assigning it tofoo
, by the way), make sure you include=
:(Hint: the compiler will complain at you that you're using structural types here. You're better of with
trait HasG { def g: Int }
and thenobject O extends HasG
; otherwise Scala actually uses reflection to callf.g
for some rationale that I've never quite been able to follow.)