Quite confusing about this returning code snippet types with & no =

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 different types of returns?
  • I really don't like return types. I want to call getX and add - I want to do something like clos1 (4) .getX - this is illegal. How to do it?
+4
source share
2 answers

Scala has an abbreviation for code that does not return any interesting value: omit the = sign. In Java, this will return void , i.e. Nothing at all; but in Scala, it is actually () , the only member of the type called Unit . In any case, this is one and the same thing: nothing or a meaningless placeholder.

The reason you need a meaningless placeholder is because when you write general code, you no longer have to handle cases of anything and nothing else.

Anyway:

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

is a function that explicitly returns only content without content () (which println also returns). And shorthand

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

Now there is one dastardly addition that Scala has, like many C-type languages, you can just throw the return value from what you are doing. And when you throw it away, all that's left is () . Scala will warn you about closure2 that you are doing something suspicious:

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

but still allow you to do it (as historically expected to work).

So, we summarize:

 def f {} 

is a method that returns only content without content () . If you write it completely, the syntax will be

 def f: Unit = {} 

and when you try to return a value of the wrong type, instead of complaining, it throws the value and gives you the type Unit , but usually gives a warning:

 def f: Unit = 5 def f { 5 } 

(Please note that opinion is mainly related to short forms these days (these days it is 2.10-stable), largely because in the absence of a clear explanation of the difference, new users often skip = without realizing it, and then wonder why doesn’t it work. So, in the future (2.11 or 2.12 for obsolescence?) the form def f {} may not work.)

If you really want to get the return value - because, for example, you want to return your O object (which you can do directly without first assigning foo , by the way), make sure you include = :

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

(Hint: the compiler will complain about you using structural types here. Better with trait HasG { def g: Int } and then object O extends HasG ; otherwise, Scala actually uses reflection to call fg for some that I never could follow.)

+15
source

I think Rex explained the reason you omitted = when define closure2 , which makes the Scala compiler, that you want to return nothing, even if you intend to return 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 

Note that the return type closure3 is 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) doesn't return anything, so you cannot call getX

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

Source: https://habr.com/ru/post/1498275/


All Articles