Java kodDlaczego jest różnica między pamięcią podręczną lambda Java 8 i Scala2.12?
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
}
}
kod Scala (wersja 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
}
}
wynik
$ 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/2[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
Najbliższym odpowiednikiem Java dla zachowania Scala byłoby, gdyby lambda main :: intSemigroup2 przechwyciła instancję Semigroup2.Foo, jak (a1 + a2) -> {foo.hashCode(); return a1 + a2; }). Zmusiłoby to Main :: intSemigroup2 do zawsze zwracania nowej wartości lambda, ponieważ Java nie ma gwarancji, że przechwycona wartość Foo jest wbudowana. – srborlongan
@srborlongan Przypuszczam, że tak - Myślałem o tym bardziej jako "dlaczego Scala nie zwraca tej samej funkcji", w przeciwieństwie do "dlaczego Java nie zwraca różnych funkcji." "Dobry punkt" – Alec
Ostatni akapit wymaga korekty. Java, zagnieżdżone interfejsy zawsze są niejawnie 'statyczne', więc' Semigroup2 .Foo' to * nie * typ, istnieje tylko 'Semigroup2.Foo', pojedynczy interfejs, natomiast typ' Semigroup2 .Bar' * jest * ogólny, więc * koncepcyjnie *, 'Semigroup2 .Bar' i' Semigroup2 .Bar' są różnymi typami, ale ze względu na * typ wymazania *, będzie tylko jedna 'Klasa' reprezentująca' Semigroup2.Bar'. –
Holger