The argument f
in your apply
function is a Funcion1
which takes a call-by-name parameter of type A
and returns a B
. Therefore, f(x)
will not evaluate the call-by-name parameter x
, but pass its reference directly to f
.
It is helpful to understand res
as follows:
def res[C]: Int = apply[C, Int](const, ???)
where in your example C
would be an unspecific type. Now what is the type parameter inferred for const
in this line? It is => C
. Unfortunately you cannot type that parameter:
def res[C]: Int = apply[C, Int](const[=> C], ???) // illegal syntax
But you can verify what is going on:
def res[C]: Int = apply[C, Int](const[Nothing], ???)
giving you
<console>:10: error: type mismatch;
found : Nothing => Int
required: => C => Int
def res[C]: Int = apply[C, Int](const[Nothing], ???)
^
This type appears inside const
as a Function0[Int]
(so Scala implicitly treats call-by-name or "thunk" arguments as a function with no arguments). Again you can verify this:
def const[A](ignored: A): Int = if (ignored.isInstanceOf[Function0[_]]) 1 else 0
Now Test.res
will give you 1
(meaning that ignored
is indeed a Function0
).
So to answer the question a different way, const
has an eager argument of type A
, but that doesn't matter here because A
becomes a function in your example, and you never apply that function, therefore ???
is never executed.
There is some debate as to why there is both a "thunk" or parentheses-less function and an empty-paren function (Function0
) in Scala.