Javaの新しい開発は、ScalaやClojureなどの言語との相互運用性にどのように影響しますか?


11

私の知る限り、ScalaとClojureはどちらも新しい言語として設計されています。

  1. JVMに依存する
  2. ScalaおよびClojureコード内でJavaクラスを使用できるという意味で、Javaコードと簡単に統合できます。

Java 8(以降のバージョンのJavaではさらに強力になる可能性があります)から、Java言語のセマンティクスに変更が加えられます。

これらの変更がJavaとScala / Clojureの間の相互運用性にどのように影響し、どのような結果になるかを尋ねたかったのです。たとえば、Java 8のラムダはオブジェクトではないため(ここを参照)、ScalaとClojureはオブジェクトではないJava値を処理する必要がある場合があります。これは問題になりますか?

次のシナリオを考えることができます。

  1. ScalaまたはClojure言語は、新しいJavaセマンティクス(新しい非オブジェクト値を処理する)に適応するように拡張され、Javaとの相互運用性をサポートします。
  2. ScalaまたはClojure言語は拡張されません。これは、関数値などの新しいJava機能を既存の概念にマッピングできる場合にのみ可能です。たとえば、Scalaでは関数もオブジェクトであるため、Java関数はScalaから見えるようになったときに再び何らかのオブジェクトにラップされると思います。
  3. ScalaまたはClojure言語は、最新のJavaの開発に従うことなく、引き続きJava 6または7までの相互運用性をサポートします。これには、Javaのより保守的で安定したブランチに基づいてこれらの言語を使用できるように、Javaの古いバージョンが(少なくともOpenJDKまたは別のプロジェクトで)サポートされている必要があります。

要約:Javaの将来の開発がScalaやClojureなどの言語に影響を与え、Javaとの相互運用性を維持できると期待できますか?このトピックに関する進行中の議論は既にありますか?

注意

Scala、Clojure、およびその他のJVMベースの言語では、実装をJVMの新しいバージョンに更新するのに大きな問題はないことを想像できます(新しいJVM機能により、この実装がさらに簡単になります)。私の質問は、言語としてのJavaの機能と、JVMベースの言語が最新のJVMで実行されるかどうかではなく、他のJVM言語がこれらの新機能を「見る」/使用する方法に焦点を当てています。


6
ScalaなどがJavaに依存していると言うのは不正確です。これらは、JVMバイトコードに依存しています。すべての相互運用機能は、Java言語のソースコードではなくバイトコードを処理するため、Java自体に加えられた変更は脅威になりません。JVMに加えられた変更のみがこれらの言語に影響を与える可能性があり、JVMは非常に保守的です-基本的には何のサポートも削除しません。実際には、JVMの中で最も変化が、最近、特に意図されているため、新しい動的な言語。
キリアンフォス

@Kilian Foth:私の知る限り、Scala StringはJava Stringです。そのため、Scalaは特定のJavaライブラリクラスを使用します。しかし、あなたがそれが強すぎると思うなら、私は処方を変えることができます。
ジョルジオ

@Kilian Foth:私の質問の焦点は、ScalaとJavaの相互運用性にあるため、「依存」という用語を削除しました。ClojureとJava。
ジョルジオ

@KilianFoth質問の主要な懸念に対処するため、これは答えになるはずです。新しいJavaリリースの最大の目標は、下位互換性です。
maple_shaft

3
@maple_shaft:質問を修正し、「depend」という単語を削除しました。別のコメントで指摘したように、私の問題はScalaまたはClojureがJavaまたはJVM機能に依存する方法ではなく、Scala / ClojureがJava機能を「見る」方法です。私の知る限り、クラス、インターフェース、オブジェクト、メソッド、プリミティブデータ型などのJava 6機能を見ることができます。これにより、Scala / ClojureはJava 6コードを使用(呼び出し)できます。私の質問は、これらの言語は将来のJava言語構造を「参照」し(したがって、使用できるようになる)、それともScala / Clojure言語の拡張が必要になるのでしょうか?
ジョルジオ

回答:


15

実際、Java 8は、Javaと相互運用する他のJVM言語にとって有害なものをあまり導入していません。Lambdasで行われた作業は、invokedynamic、MethodHandles、MethodReferencesなどに関するいくつかの小さな問題を修正するのに役立ちましたが、それ以外は通常どおり実行されます。そうは言っても、他のJVM言語が潜在的に呼び出すことができるAPIのまったく新しい束があります。彼らがデフォルトで使用するかどうかは、彼ら次第です。

相互運用に影響を与える最大の変更は、実際にはJava 7で発生しました-JVM内で動的/遅延バインディング呼び出しを可能にするinvokedynamicバイトコード-JVMの他の言語用に最初に設計されたものです。それ以来、非常に便利にLamdbasに適合しているため、Java 8の時点で、Javaは実際にこれらのバイトコードの発行を開始します。

一部の言語(たとえばJRuby)はすでにinvokedynamicを頻繁に使用していますが、他の言語(Scala、Groovyなど)はまだその使用を調査しているか、パッチを適用する初期段階にあります。過去に使用を余儀なくされた無数の低速な回避策とは対照的に、Javaは静的呼び出しを呼び出します。

Java 9は、JVM用の従来のクラスローディングとクラスパスの終わりの始まりとなるプロジェクトJigsawがプラットフォームに登場することにより、JVM言語により多くの課題をもたらします。JVM言語の人々はこれをかなり認識しており、賢明な共同作業が行われることを期待しています。


1
しかし、私が知る限り、Scalaクロージャーはオブジェクトです。
ジョルジオ

1
うん。ScalaがJava 1.5のサポートをやめたのはごく最近のことで、1.6を落とすまでには長い時間がかかります。
ヨルグWミットタグ

1
@Giorgio Javaの言語機能は重要ではありません。それらのほとんどは、とにかくコンパイルされたときにバイトコードのトリックに相当します。新しいバイトコードが導入されても、JVMが常に後方互換性があることを受け入れると、Scalaは影響を受けず、都合の良いときにこれらの新しいJVM機能を利用することを選択できます。
maple_shaft

1
「Javaの言語機能は、とにかくコンパイル時にバイトコードトリックに相当するため、重要ではありません。」:別の言語がJavaコンストラクトを使用する場合、そのコンストラクトに対して生成されたバイトコードを認識できる必要があります。Javaが新しいバイトコードにマップする新しいコンストラクトを導入する場合、ホスト言語は少なくとも新しいバイトコードを認識して使用するための新しいラッパー/インターフェースを実装する必要があります。たとえば、Java 8ラムダがオブジェクトを作成せず、新しい特定のバイトコードを持つ新しいコンストラクトを作成した場合、ホスト言語はそれを認識するように適合させる必要があります。
ジョルジオ

2
@Giorgio:もちろんですが、Java 8プラットフォームではそのような変更は予定されていません。実際、JVMSは2003年と2010年にJavaプラットフォームの歴史全体で2回だけ拡張れました。2回目(invokedynamicバイトコードの導入)は、Java以外の言語をサポートするためものでした。実際、Java 7言語そのバイトコードをサポートまたは使用していません
ヨルグWミットタグ

2

Javaラムダは使用されているコンテキストに応じて型が割り当てられるため、Javaがラムダを追加するとScalaは取り残されようとしますが、Scalaラムダはアリティ、パラメータ型、戻り値型に基づいて型を割り当てられます。

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

Java 8からScalaで次のように記述できます。

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

Scalaの()=> UnitをRunnableに変換するラッパーを使用/作成しない限り。


答えてくれて、私の質問に答えてくれてありがとう(+1)。正しく理解できれば、Scalaは引き続き匿名クラスを使用して、Java 8がラムダを使用するコンテキストでインターフェースをインスタンス化する必要があります(Java 8ラムダはScalaラムダとは異なるセマンティクスを持つため)。私にとって明確ではないもう1つの点は、JavaメソッドがJavaラムダを返すとどうなるかということです。Scalaクラスがそのメソッドを呼び出すとどうなりますか?Scalaの戻り値の型は何ですか?
ジョルジオ

1
@Giorgio Java 8では、ラムダ式は言語レベルのショートカットであり、単一のメソッドを宣言し、コンテキストによって延期されるインターフェイスのインスタンスを作成します。そのため、Java 8メソッドがラムダを返すとき、メソッドの戻り値の型として宣言されているインターフェイスのインスタンスを実際に返します。Scala 2.9.1の時点では、戻り型は、Scalaライブラリの暗黙の変換を導入しない限り、Scalaラムダとして扱うことができないインターフェース(RunnableまたはComparator)のインスタンスになります。Scalaラムダ型へのインターフェース。
-hellodanylo

@SkyDan:OK、ScalaはJavaラムダを何らかのインターフェースを実装するオブジェクトと見なします。この点は私には明確ではありませんでした。Javaは、オブジェクトのバイトコードとは異なるバイトコードを生成すると考えました。ただし、内部のオブジェクトである必要があります。そうでない場合、インターフェイスの実装として認識されません。今手に入れたと思う。
ジョルジオ

@Giorgio、また、Java 8のラムダ関連の変更とこれらの変更を推進する力について詳しく知りたい場合は、Lambdaプロジェクトのこの魅力的で詳細な概要を読むことをお勧めします。
hellodanylo

@SkyDan:今すぐ読んで。ラムダオブジェクトを表しているようです(タイプ/インターフェースは、それらが定義されているコンテキストから推測されますが)。したがって、mail.openjdk.java.net / pipermail / lambda-dev / 2011-August /…(「ラムダはオブジェクトではありません」)で提供される情報は正しくないか、少なくとも誤解を招く恐れがあります。
ジョルジオ
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.