Неоднозначная перегрузка, даже более конкретная - PullRequest
3 голосов
/ 16 июня 2019

У меня есть два определения foo, и одно из них более предположительно

def foo(f: java.util.function.ToIntFunction[String]) = println("foo1")
def foo[T](f: String=>T) = println("foo2")
//def foo[T](f: String=>T)(implicit d: DummyImplicit) = println("foo2")    //Does not work either


foo({_: String => 1})            //Should pick foo1, but gives error instead

Ошибка:

error: ambiguous reference to overloaded definition,
both method foo in object Main of type [T](f: String => T)Unit
and  method foo in object Main of type (f: java.util.function.ToIntFunction[String])Unit

Я также попробовал трюк DummyImplicitно это все равно дает ту же ошибку.Как я могу добиться перегрузки времени компиляции, когда Int представляет без отражения?

Я использую Scala 2.12 с поддержкой типа SAM.


Редактировать

Я надеюсь получить решение, которое не ограничивается использованием Java-конвертеров, поскольку интерфейс ToIntFunction можно заменить на черту Scala, например,

trait ToIntFunction[T] { def apply(v: T): Int }
def foo(f: ToIntFunction[String]) = println("foo1")
def foo[T](f: String=>T) = println("foo2")

, так как я считаю, что это более общая проблема для методаперегрузки.

Ответы [ 2 ]

1 голос
/ 17 июня 2019

Я нашел решение, используя расширение макроса:

object Foo {
    import scala.reflect.macros.Context
    import scala.language.experimental.macros

    def foo[T,R](f: T=>R) = macro fooImpl[T,R]

    def fooImpl[T: c.WeakTypeTag, R: c.WeakTypeTag](c: Context)
        (f: c.Expr[T=>R]): c.Expr[Unit] = {
        import c.universe._
        if(c.weakTypeOf[R] == c.weakTypeOf[Int]) {
            reify { println("Int") }
        }
        else {
            reify { println("Not Int") }
        }
    }
}

В другом файле,

object Test extends MainApp {
  Foo.foo {_:String => 0}    //expands into a simple println and it prints "Int"
  Foo.foo {_:String => 0d}   //prints "Not Int"
}

Это определенно не идеально, но решает проблему. Надеюсь, что кто-то может дать ответ без использования макроса.

1 голос
/ 17 июня 2019

На моей машине с Scala 2.12 foo({_: String => 1}) оценивается как foo2, поэтому я не могу воспроизвести проблему.Моя интерпретация преобразования SAM в разрешении перегрузки в Scala 2.12 состоит в том, что Function -типированные аргументы имеют приоритет, поэтому его следует оценивать как foo2:

Для улучшениясовместимость с исходным кодом, разрешение перегрузки было адаптировано для предпочтения методов с аргументами типа Function, а не методов с параметрами типов SAM.

Примечание _: String => 1 равно Function1.Чтобы заставить его оценить foo1, попробуйте asJava из scala-java8-compat примерно так:

import scala.compat.java8.FunctionConverters._
foo({_: String => 1}.asJava) // foo1

Согласно комментарию Кшиштофа Атласика, оно воспроизводимо в Scala 2.13.

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