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 whatprintlnreturns 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 onclosure2that 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.gfor some rationale that I've never quite been able to follow.)