Почему `def hello[T](f: => T) = f; hello(()=>12)`компилируется, но`def hello(f: => Int) = f; привет (() => 12) `нет?
Следующий код может быть скомпилирован:
def hello[T](f: => T) = f
hello(() => 12)
Но следующий не:
def hello(f: => Int) = f
hello(() => 12)
Который сообщает об ошибке:
<console>:9: error: type mismatch;
found : () => Int
required: Int
hello(() => 12)
Зачем?
2 ответа
Я бы сказал, потому что T
может быть любым () => x
, но Int
не может быть () => x
,
В вашей ситуации вы проходите () => 12
в качестве параметра, который является судебным иском, потому что T
не имеет ограничений и может быть чем угодно, фактически возвращая частично примененную функцию:
scala> def hello[T](f: => T) = f
hello: [T](f: => T)T
scala> hello(()=>12)
res1: () => Int = <function0>
Что вы можете назвать так:
scala> res1()
res2: Int = 12
Во втором случае вместо этого вы передаете функцию из Unit
в Int
который не является Int
(возвращает Int
но это не Int
).
Дело в том, что f
передается как параметр по имени, здесь не имеет значения:
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)
Не путайте это: f: => T
с этим: f: () => T
это разные вещи, чтобы было понятно
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>
Теперь он компилируется в обоих случаях, потому что f
это функция от Unit
в T
в первом случае (где T
конечно может быть Int
) и во втором случае f
это функция от Unit
в Int
и вы можете пройти () => 12
в качестве параметра.
Это просто из-за того, что => T
не то же самое, что () => T
...
=> T
это имя по имени, что означает
def hello(f: => Int) = f
Предполагается, что называется так:
hello(12)
Причина def hello[T](f: => T) = f
работает с () => 12
потому что вы кладете в Function0[Int]
на месте Т, который отличается от просто Int
Чтобы сделать () =>
Синтаксис работает, как и ожидалось, рассмотрите возможность сделать это:
def hello(f: () => Int) = f // can also be written as:
def hello(f: Function0[Int]) = f
Теперь ваша функция ожидает Function0
где это не было раньше, и hello(() => 12)
будет работать как положено