问题
Following code can be compiled:
def hello[T](f: => T) = f
hello(() => 12)
But following not:
def hello(f: => Int) = f
hello(() => 12)
Which reports error:
<console>:9: error: type mismatch;
found : () => Int
required: Int
hello(() => 12)
Why?
回答1:
I would say because T
can be any () => x
, but Int
can't be a () => x
.
In your situation you are passing () => 12
as parameter which is a legal action because T
has no constrains and can be anything, in fact doing so returns a partial applied function:
scala> def hello[T](f: => T) = f
hello: [T](f: => T)T
scala> hello(()=>12)
res1: () => Int = <function0>
That you can call so:
scala> res1()
res2: Int = 12
The second case instead you are passing a function from Unit
to Int
which is not an Int
(it returns an Int
but it's not an Int
).
The fact that f
is passed as call by name parameter doesn't make any difference here:
scala> def hello[T](f: T) = f
hello: [T](f: T)T
scala> hello(()=>12)
res11: () => Int = <function0>
scala> def hello(f: Int) = f
hello: (f: Int)Int
scala> hello(()=>12)
<console>:9: error: type mismatch;
found : () => Int
required: Int
hello(()=>12)
Don't confuse this: f: => T
with this: f: () => T
, they are different things, to make it clear:
scala> def hello[T](f: () => T) = f
hello: [T](f: () => T)() => T
scala> hello(()=>12)
res13: () => Int = <function0>
scala> def hello(f: () => Int) = f
hello: (f: () => Int)() => Int
scala> hello(()=>12)
res14: () => Int = <function0>
Now it compile in both cases because f
is a function from Unit
to T
in the first case (where T
can of course be an Int
) and in the second case f
is a function from Unit
to Int
and you can pass () => 12
as parameter.
回答2:
It's simply due to the fact that => T
not being the same as () => T
...
=> T
is call by name, meaning
def hello(f: => Int) = f
Is supposed to be called like this:
hello(12)
The reason def hello[T](f: => T) = f
works with () => 12
is because you're putting in a Function0[Int]
on T's spot, which is different from just an Int
To make the () =>
syntax work as expected, consider doing this:
def hello(f: () => Int) = f // can also be written as:
def hello(f: Function0[Int]) = f
NOW your function expects a Function0
, where it didn't before, and hello(() => 12)
will work as expected
来源:https://stackoverflow.com/questions/25473637/why-def-hellotf-t-f-hello-12-is-compilable-but-def-hellof