W jaki sposób nowy rozwój Java wpłynie na jego interoperacyjność z takimi językami jak Scala i Clojure?

11

O ile rozumiem, zarówno Scala, jak i Clojure zostały zaprojektowane jako nowe języki, które

  1. zależą od JVM i
  2. łatwo integrują się z kodem Java w tym sensie, że pozwalają na korzystanie z klas Java wewnątrz kodu Scala i Clojure.

Począwszy od Java 8 (a może jeszcze mocniej w kolejnych wersjach Java), nastąpią zmiany w semantyce języka Java.

Chciałem zapytać, jak te zmiany wpłyną na interoperacyjność między Javą a Scalą / Clojure i jakie będą tego konsekwencje. Na przykład, ponieważ lambdy w Javie 8 nie są obiektami (patrz np. Tutaj ), Scala i Clojure mogą mieć do czynienia z wartościami Java, które nie są obiektami. Czy to byłby problem?

Mogę wymyślić następujące scenariusze:

  1. Język Scala lub Clojure zostanie rozszerzony w celu dostosowania do nowej semantyki Java (w celu obsługi nowych wartości niebędących obiektami) i obsługi interoperacyjności z Javą.
  2. Język Scala lub Clojure nie zostanie przedłużony. Byłoby to możliwe tylko wtedy, gdyby nowe funkcje Java, takie jak wartości funkcji, można było odwzorować na istniejące pojęcia. Np. W Scali nawet funkcja jest obiektem, więc sądzę, że funkcje Java byłyby ponownie zawinięte w jakieś obiekty, gdy staną się widoczne dla Scali.
  3. Język Scala lub Clojure będzie nadal obsługiwał interoperacyjność do wersji Java 6 lub 7, bez śledzenia najnowszych osiągnięć Javy. Wymagałoby to, aby starsze wersje Java były nadal obsługiwane (przynajmniej przez OpenJDK lub inny projekt), aby te języki mogły być oparte na bardziej konserwatywnej / stabilnej gałęzi Java.

Podsumowując: czy możemy oczekiwać, że przyszły rozwój Java będzie miał wpływ na języki takie jak Scala i Clojure, aby zachować interoperacyjność z Javą? Czy jest już jakaś (prowadząca do) dyskusja na ten temat?

Uwaga

Mogę sobie wyobrazić, że Scala, Clojure i inne języki oparte na JVM nie będą miały większych problemów z aktualizacją ich implementacji do nowszych wersji JVM (i że nowe funkcje JVM jeszcze bardziej ułatwią tę implementację). Moje pytanie dotyczy funkcji Java jako języka i tego, czy / jak inny język JVM będzie w stanie „zobaczyć” / korzystać z tych nowych funkcji, a nie tego, czy języki oparte na JVM będą działały na najnowszych JVM.

Giorgio
źródło
6
Mówienie, że Scala itp. Zależy od Javy, jest nieprecyzyjne. Zależą od kodu bajtu JVM. Wszystkie funkcje interoperacyjności dotyczą kodu bajtowego, a nie kodu źródłowego języka Java, więc wszelkie zmiany wprowadzone w samej Javie nie stanowią zagrożenia. Tylko zmiany wprowadzone w JVM mogą mieć wpływ na te języki, a JVM jest wyjątkowo konserwatywny - w zasadzie nigdy nie usuwa obsługi czegokolwiek. W rzeczywistości większość zmian w JVM jest obecnie przeznaczona specjalnie dla nowszych języków dynamicznych.
Kilian Foth
@Kilian Foth: O ile mi wiadomo, Scala Stringto Java String. Dlatego Scala używa pewnych klas bibliotek Java. Ale mogę zmienić sformułowanie, jeśli uważasz, że jest zbyt silny.
Giorgio
@Kilian Foth: Usunąłem termin zależny, ponieważ moje pytanie skupia się raczej na interoperacyjności między Scala i Java. Clojure i Java.
Giorgio
@KilianFoth To powinna być odpowiedź, ponieważ odnosi się do głównej troski pytania. Najważniejszym celem każdej nowej wersji Java jest kompatybilność wsteczna.
wałek klonowy
3
@maple_shaft: Poprawiłem swoje pytanie i usunąłem słowo „depend”. Jak zauważyłem w innym komentarzu, moim problemem nie jest to, w jaki sposób Scala lub Clojure zależą od funkcji Java lub JVM, ale w jaki sposób Scala / Clojure może „zobaczyć” funkcje Java. O ile mi wiadomo, widzą funkcje Java 6, takie jak klasy, interfejsy, obiekty, metody, prymitywne typy danych. Dzięki temu Scala / Clojure może używać (wywoływać) kod Java 6. Moje pytanie brzmi: czy te języki również „widzą” (a zatem będą w stanie używać) przyszłe konstrukcje języka Java, czy też wymagałoby to rozszerzenia języków Scala / Clojure?
Giorgio

Odpowiedzi:

15

W rzeczywistości Java 8 nie wprowadza wiele, co byłoby szkodliwe dla innych języków JVM współpracujących z Javą. Prace wykonane w Lambdas pomogły rozwiązać wiele drobnych problemów związanych z wywoływanymi dynamicznymi, MethodHandles, MethodReferences itd. - ale poza tym jest to normalne. To powiedziawszy, istnieje zupełnie nowa grupa interfejsów API, do których potencjalnie mogłyby teraz zadzwonić inne języki JVM. To, które będą używać domyślnie, czy nie, zależy od nich.

Największa zmiana mająca wpływ na interop faktycznie pojawiła się w Javie 7 - z wywoływanym dynamicznym kodem bajtowym, który umożliwia dynamiczne / późne wiązanie wywołań w JVM - coś, co początkowo zostało zaprojektowane dla innych języków JVM. Od tego czasu został bardzo użytecznie dostosowany do Lamdbas, więc od Java 8 Java zacznie emitować te kody bajtowe.

Niektóre języki (na przykład JRuby) już intensywnie używają invokedynamic, podczas gdy inne (Scala, Groovy i in.) Wciąż badają jego użycie lub są na wczesnych etapach łatania go. Teoretycznie sprawia, że ​​ich dynamiczne wywołania są prawie tak wydajne jak istniejące Wywołania invokestatic Java, w przeciwieństwie do niezliczonej liczby wolniejszych obejść, których musieli używać w przeszłości.

Java 9 przyniesie więcej wyzwań dla języków JVM wraz z projektem Jigsaw wchodzącym na platformę, która będzie początkiem końca tradycyjnego ładowania klas i ścieżek klas dla JVM. Ludzie języka JVM są tego świadomi i oczekuję rozsądnej współpracy.

Martijn Verburg
źródło
1
Ale, o ile mi wiadomo, zamknięcie Scali jest przedmiotem.
Giorgio
1
Tak. Scala dopiero niedawno zrezygnował z obsługi Java 1.5, minie dużo czasu, nim upuszczą 1.6.
Jörg W Mittag
1
@Giorgio Funkcje językowe Javy są nieistotne, ponieważ większość z nich przy kompilacji odpowiada sztuczkom z kodem bajtowym. Jeśli zaakceptujemy, że JVM będzie zawsze kompatybilny wstecz, nawet jeśli zostaną wprowadzone nowe kody bajtowe, wówczas Scala pozostanie nienaruszona i może zdecydować się na skorzystanie z tych nowych funkcji JVM w dogodny dla siebie sposób.
wałek klonowy
1
„Funkcje językowe języka Java są nieistotne, ponieważ większość z nich przy kompilacji odpowiada sztuczkom z kodem bajtowym.”: Jeśli inny język chce użyć konstrukcji Java, musi być w stanie rozpoznać kod bajtowy wygenerowany dla tej konstrukcji. Jeśli Java wprowadza nowe konstrukcje, które są mapowane na nowy kod bajtowy, język hosta powinien przynajmniej zaimplementować nowe opakowanie / interfejs, aby rozpoznać i użyć nowego kodu bajtowego. Np. Jeśli lambda Java 8 nie utworzyła obiektu, ale jakiś nowy konstrukt z nowym, specyficznym dla niego kodem bajtowym, język hosta musi być przystosowany do rozpoznawania go.
Giorgio,
2
@Giorgio: Jasne, ale nie są planowane takie zmiany dla platformy Java 8. W rzeczywistości JVMS został rozszerzony tylko dwukrotnie w całej historii platformy Java, w 2003 i 2010 roku, a drugi raz (wprowadzenie invokedynamickodu bajtowego) był specjalnie przeznaczony do obsługi języków innych niż Java; w rzeczywistości język Java 7 nie obsługuje tego kodu bajtowego ani go nie używa.
Jörg W Mittag,
2

Scala ma zamiar pozostać w tyle, gdy Java dodaje lambdy, ponieważ lambdom Java przypisuje się typ zgodnie z kontekstem, w którym są używane, podczas gdy Scala lambdom przypisuje się typ na podstawie ich arancji, typów parametrów i typów zwracanych, więc np.

executor.execute(() -> { System.out.println("hello world"); });

z Java 8 można zapisać w Scali jako:

executor execute new Runnable {
    override def run() { println("hello world") }
}

chyba że użyjesz / napiszesz jakieś opakowania konwertujące Scala's () => Unit na Runnable.

Ricky Clarkson
źródło
Dziękuję za odpowiedź, a także za odpowiedź na moje pytanie (+1). Jeśli dobrze zrozumiem, Scala będzie musiała nadal używać anonimowych klas do tworzenia instancji interfejsów w kontekście, w którym Java 8 będzie używać lambdas (ponieważ lambda Java 8 mają inną semantykę niż lambda Scala). Innym zagadnieniem, które nie jest dla mnie jasne, jest to, co się stanie, jeśli metoda Java zwróci lambda Java. Co się stanie, jeśli klasa Scala wywoła tę metodę? Jaki będzie typ zwrotu w Scali?
Giorgio
1
@Giorgio W Javie 8 wyrażenie lambda jest skrótem na poziomie języka, aby utworzyć instancję interfejsu, która deklaruje pojedynczą metodę i która jest odroczona przez kontekst. Tak więc, gdy metoda Java 8 zwraca lambda, faktycznie zwraca instancję interfejsu zadeklarowaną jako typ zwracany przez metodę. Jak Scala 2.9.1, typ zwracany będzie po prostu instancją Niektórzy mówią interfejsu (Runnable lub komparatora), które można nie traktować jako lambda Scala, chyba że ani przyszłe wersje Scala libary wprowadzić niejawna konwersja z że interfejs do typu Scala lambda.
hellodanylo
@SkyDan: Ok, więc Scala zobaczy lambda Java jako obiekty implementujące jakiś interfejs. Ten punkt nie był dla mnie jasny: myślałem, że Java wygeneruje kod bajtowy inny niż kod obiektu. Ale musi to być obiekt pod maską, w przeciwnym razie nie zostałby rozpoznany jako implementacja interfejsu. Chyba już to mam.
Giorgio
@Giorgio, również jeśli chcesz dowiedzieć się więcej o zmianach związanych z lambda w Javie 8 i siłach, które je napędzają, polecam przeczytanie tego fascynującego i szczegółowego przeglądu projektu Lambda .
hellodanylo
@SkyDan: Czytam to teraz. Wydaje mi się, że lambdas zrobić stanowią obiekty (mimo że typ / interfejs jest wywnioskować z kontekstu, w którym są zdefiniowane). Tak więc informacje podane na mail.openjdk.java.net/pipermail/lambda-dev/2011-August/... („ lambdas nie są obiektami”) są nieprawidłowe lub przynajmniej wprowadzają w błąd.
Giorgio,