What happens in this code?


#1

I’m wondering why this compiles and runs. Is it related to omitting parentheses Feature maybe?

Welcome to the Ammonite Repl 1.1.2
(Scala 2.12.6 Java 1.8.0_172)
If you like Ammonite, please support our development at www.patreon.com/lihaoyi
@ def test(n: Unit): Int = 32
defined function test
@ test(1111)
res1: Int = 32
@ test("blabla")
res2: Int = 32

It is obviously a contrived example. I don’t understand why that works, can maybe someone tell me what the compiler does here?

Thank you and kind regards
Eike


#2

You didn’t indicate why you thought it wouldn’t do what it does, so I’m going to have to guess what you mean.

I’m guessing that you’re being puzzled by unit insertion. The most evocative example of this feature is

val x: Unit = 7

This is specified in 6.26.1§Value discarding:

Implicit conversions can be applied to expressions whose type does not match their expected type, […]
If e has some value type and the expected type is Unit, e is converted to the expected type by embedding it in the term { e; () }.

EDIT, if you don’t like this feature, consider compiling under -Ywarn-value-discard


#3

Thank you for your answer. Sorry that I wasn’t clear. You guessed correctly, I was assuming that I could not put an Int as an argument into a method that expects a unit.

Thank you for pointing me to the relevant spec. I was not aware of this specific implicit conversion.


#4

Personally, I consider this a bit of a misfeature, and the fewer of these “you probably meant x let me silently do that for you” features the better IMO, but opinions tend to differ on that - if it were up to me, the language wouldn’t have overloading or call-by-name either (at least in its current form), and there are very few people who agree with me on that I think


#5

I guess the original poster meant: why is f(x: Unit) allowed, when it appears to be so useless?

(And as far as I can tell, it has nothing to do with omitting parentheses.)

I suppose it is for consistency. Because f(x: => Unit) is very useful (think Try{…} or Future{…}), as is f(x: A), where A may sometimes be Unit.

The question remains, how will such a method look on the JVM side? Is the argument eliminated, or is the Unit boxed, or what happens?


#6

I see that it is useful to have a parameter of type Unit. I meant
actually why it is allowed to call a method with an argument that has
different type than the defined parameter. I came across this having a
f(a: A) where A was Unit in one case. I wasn’t aware that any
value is converted to Unit implicitly and that puzzled me. I tried to
explain it to myself, trying for example with the omitting-parentheses
syntax, but failed…. Well, now that I know it is due to an implicit
conversion, I should have guessed something like that :slight_smile:

Oliver Ruebenacker noreply@users.scala-lang.org writes:


#7
scala> class Foo { def foo(u: Unit) = u }
defined class Foo

scala> :javap -filter -cp Foo
Compiled from "<console>"
public class Foo {
  public void foo(scala.runtime.BoxedUnit);
    Code:
       0: return

  public Foo();
    Code:
       0: aload_0
       1: invokespecial #23                 // Method java/lang/Object."<init>":()V
       4: return
}