Ich lief in eine seltsame Diskrepanz zwischen Funktionen und Objekten (scala 2.10):Implizite Konvertierungen für Defs/Lambdas in Scala?
implicit def conv(c: Int => String) : (PrintStream => Int => Unit) = p => v => p.println(c(v))
def f(h: PrintStream => Int => Unit) : Unit = h(System.out)(1)
def a(x: Int) = x.toString
val b = (x: Int) => x.toString
// def main(args: Array[String]) = f(a) // fail
// def main(args: Array[String]) = f((x: Int) => x.toString) // fail
def main(args: Array[String]) = f(b) // ok
Warum gibt es einen Unterschied zwischen defs/Lambda-Literale und Lambda-vals?
Update: Offenbar tritt das Problem nicht für binäre Funktionen auftreten: Implicit conversion of a function to a second-order-function only works if the function to convert has at least two parameters
Ich habe diese, und in der Tat der folgende Code funktioniert:
implicit def conv(c: (Int,Unit) => String) : (PrintStream => Int => Unit) = p => v => p.println(c(v,()))
def f(h: PrintStream => Int => Unit) : Unit = h(System.out)(1)
def a(x: Int, y : Unit) = x.toString
val b = (x: Int, y : Unit) => x.toString
def main(args: Array[String]) = f(a) // ok
def main(args: Array[String]) = f((x: Int, y: Unit) => x.toString) // ok
def main(args: Array[String]) = f(b) // ok
Ebenso Nullary Funktionen stellen kein Problem entweder:
implicit def conv(c:() => String) : (PrintStream => Int => Unit) = p => v => p.println(c())
def f(h: PrintStream => Int => Unit) : Unit = h(System.out)(1)
def a() = "1"
val b =() => "1"
def main(args: Array[String]) = f(a) // ok
def main(args: Array[String]) = f(() => "1") // ok
def main(args: Array[String]) = f(b) // ok
Also, die Frage neu zu formulieren: warum ist dies nicht für unäre Methoden und Funktionen arbeiten?
Update: Das Problem scheint auch auf den Zieltyp (der Typ von fs Argument h) bezogen zu sein. Die folgende funktioniert auch (diesmal zugunsten von „eta-Expansion zählt als hop“, weil wir eine Methode Wert aus einer mit _ erstellen müssen)
implicit def conv(c: Int => String) : Unit =()
def f(h: Unit) : Unit = System.out.print("?")
def a(x: Int) = x.toString
val b = (x: Int) => x.toString
def main(args: Array[String]) = f(a _) // ok
def main(args: Array[String]) = f((x: Int) => x.toString) // ok
def main(args: Array[String]) = f(b) // ok
m aybe scalac betrachtet die Umwandlung von defs/lambda Literals in FunctionN bereits als impliziten Hop (von denen höchstens eins erlaubt ist)? –
Überprüfen Sie nur die Spezifikationen. Eta-Erweiterung sollte kostenlos sein, so sollten die drei gleichwertig sein. View application: "Wir sagen, ein Typ T ist kompatibel zu einem Typ U, wenn T nach Anwendung von eta-expansion * und * view-Anwendungen schwach mit U übereinstimmt." –
http://stackoverflow.com/questions/28456012/implicit-conversion-of-a-function-to-a-second-order-function-only-works-i-f-the-f –