Java-CodeWarum gibt es einen Unterschied zwischen Java8 und Scala2.12 Lambda Cache?
package lambda_cache_example_java;
interface Semigroup1<A> {
public A append(A a1, A a2);
}
interface Semigroup2<A> {
public A append(A a1, A a2);
public interface Foo{}
public class Bar{}
}
class Main {
static Semigroup1<Integer> intSemigroup1() {
return (a1, a2) -> a1 + a2;
}
static Semigroup2<Integer> intSemigroup2() {
return (a1, a2) -> a1 + a2;
}
public static void main(String[] args) {
Semigroup1<Integer> x1 = intSemigroup1();
Semigroup1<Integer> x2 = intSemigroup1();
System.out.println(x1);
System.out.println(x2);
System.out.println(x1 == x2); // same instance
Semigroup2<Integer> y1 = intSemigroup2();
Semigroup2<Integer> y2 = intSemigroup2();
System.out.println(y1);
System.out.println(y2);
System.out.println(y1 == y2); // same instance as well
}
}
Scala-Code (Version 2.12.0)
package lambda_cache_example_scala
trait Semigroup1[A] {
def append(a1: A, a2: A): A
}
trait Semigroup2[A] {
def append(a1: A, a2: A): A
trait Foo
}
object Main {
def intSemigroup1(): Semigroup1[Int] =
(a1, a2) => a1 + a2
def intSemigroup2(): Semigroup2[Int] =
(a1, a2) => a1 + a2
def main(args: Array[String]): Unit = {
val x1 = intSemigroup1()
val x2 = intSemigroup1()
println(x1)
println(x2)
println(x1 eq x2) // same instance
val y1 = intSemigroup2()
val y2 = intSemigroup2()
println(y1)
println(y2)
println(y1 eq y2) // not same
}
}
Ergebnis
$ sbt "runMain lambda_cache_example_java.Main" "runMain lambda_cache_example_scala.Main"
[info] Running lambda_cache_example_java.Main
lambda_cache_example_java.Main$$Lambda$9/[email protected]
lambda_cache_example_java.Main$$Lambda$9/[email protected]
true
lambda_cache_example_java.Main$$Lambda$10/[email protected]
lambda_cache_example_java.Main$$Lambda$10/[email protected]
true
[success] Total time: 0 s, completed 2016/11/24 15:09:56
[info] Running lambda_cache_example_scala.Main
lambda_cache_example_scala.Main$$$Lambda$11/[email protected]
lambda_cache_example_scala.Main$$$Lambda$11/[email protected]
true
[email protected]
[email protected]9
false
[success] Total time: 0 s, completed 2016/11/24 15:09:57
Das nächste Java-Äquivalent für das Verhalten von Scala wäre, wenn das Lambda von Main :: intSemigroup2 eine Semigroup2.Foo-Instanz erfasst, wie (a1 + a2) -> {foo.hashCode(); zurückgeben a1 + a2; }). Dies würde dazu führen, dass Main :: intSemigroup2 immer ein neues Lambda zurückgibt, da Java nicht garantiert, dass der erfasste Foo-Wert inline-fähig ist. – srborlongan
@srborlongan Ich nehme an - ich dachte an die Frage mehr als "warum Scala nicht die gleiche Funktion zurückgibt" im Gegensatz zu "warum Java nicht verschiedene Funktionen zurückgibt. Guter Punkt. – Alec
Der letzte Absatz benötigt eine Korrektur Java, verschachtelte Interfaces sind immer implizit 'static', also' Semigroup2 .Foo' ist * nicht * ein Typ, es gibt nur 'Semigroup2.Foo', eine einzige Schnittstelle. Im Gegensatz dazu ist der Typ' Semigroup2 .Bar' * ist * generisch, also * konzeptionell *, 'Semigroup2 .Bar' und' Semigroup2 .Bar' sind verschiedene Typen, aber wegen * type desirasure * gibt es nur eine 'Class', die' Semigroup2.Bar' repräsentiert. –
Holger