Неявный метод преобразования функций не работает, когда передается в качестве аргумента? - PullRequest
7 голосов
/ 24 сентября 2019

Возможно, я что-то упустил, но я наткнулся на шаблон, который неожиданно не работает.
Вот оно:

object A {
  def bar(func: (Int, Int) => Int): Int = 2
  def bar(func: Int => Int): Int = 3
  def foo(func: Int => Int): Int = 4
}

def f(n: Int) : Int = n + 1
val g: Int => Int = f

A.foo(f) // works fine
A.bar(f) // doesn't work
A.bar(g) // but this works

Компилятор просит меня явно применить метод f вчтобы передать его (запись f _):
Unapplied methods are only converted to functions when a function type is expected.

Я не понимаю, почему преобразование неявно выполняется при передаче f в A.foo, но не при передаче в A.bar.Это может быть связано с тем фактом, что bar имеет две перегрузки, но я не уверен, почему?

Я использую Scalac с Scala 2.12.8.

1 Ответ

11 голосов
/ 24 сентября 2019

Сообщение об ошибке указывает вам правильное направление: как метод , f не является прямым эквивалентом значению типа Int => Int, даже если они похожи.Чтобы передать его в качестве аргумента, f необходимо преобразовать в значение, что часто, но не всегда, делается неявно.

Когда вы объявляете val g = f _ или используете A.bar(f _), вы явно конвертируете метод в значение.

Поскольку метод bar перегружен, компилятор не уверен, в какой тип вы преобразуете f (это Int => Int или (Int,Int) => Int?).Чтобы избежать какого-либо удивления, он просит вас явное преобразование.Вы также можете заставить его скомпилировать, используя A.bar(f: Int => Int), потому что это устраняет неоднозначность, явно выбрав одно из bar определений.

Компилятор может попытаться рассуждать об этом, потому что вы передаете Int => Intи неявный метод-> поднятие значения может произойти, только если вы хотите присвоить его bar(Int => Int), но в этом случае это просто не так.Для этого может быть техническая причина, например, компилятор не пытается объединить разрешения перегрузок и неявный подъем из-за комбинаторного взрыва.Я бы посчитал это небольшим ограничением компилятора, которое легко обойти, если быть более явным.Более подробное часто лучше!

Как указано в комментариях @slouc, более технические подробности по этому вопросу доступны здесь .

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...