Why `def hello[T](f: => T) = f; hello(()=>12)` is compilable but `def hello(f: => Int) = f; hello(()=>12)` is not?

眉间皱痕 提交于 2019-12-11 11:38:08

问题


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

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!