http://openjdk.java.net/jeps/126 のテキトーな訳。
JEPをもいっこくらい読んでみるかぁ~ってことで、概要レベルくらいは抑えているラムダ式んとことを読むことにした。
JEP 126: ラムダ式と仮想拡張メソッド Lambda Expressions & Virtual Extension Methods
Author Joseph D. Darcy Organization Oracle Owner Brian Goetz Created 2011/11/1 Updated 2013/2/21 Type Feature State Funded Component --/-- Scope SE JSR 269 MR, 335 Discussion lambda dash dev at openjdk dot java dot net Start 2011/Q4 Blocks 107, 109 Effort XL Duration XL Reviewed-by Brian Goetz Endorsed-by Brian Goetz Funded-by Oracle Release 8 Target M7
要約 Summary
ラムダ式(クロージャclosures)とそのサポート機能、これに付随するものとして、メソッド参照(method references)、拡張型インタフェース(enhanced type inference)、仮想拡張メソッド、をJavaプログラミング言語とプラットフォームへ追加する。
目的 Goals
ラムダ式と仮想拡張メソッドの主要機能、それに沿ったサポート機能のセット、いくつかのプラットフォーム目標。
- より抽象化されたハイパフォーマンスライブラリの消費と作成の簡素化。
- 移行互換性のあるスムーズなライブラリ進化のサポート
新しく共通な機能をJavaプログラミング言語に追加することに加えて、ラムダ式は内部イテレーションイディオム(internal iteration idioms)により改良マルチコアサポートに新しい可能性を与えます。
ラムダ周りに採用される言語機能には仮想拡張メソッドが含まれており、これはインタフェースにソースとバイナリ互換における改良をもたらします。
言語変更に加えて、coordinated libraries*1とJVM変更が同様に発生します。
注意点として、JEPプロセスで以前の日付で活動中および継続中のProject Lambda OpenJDKプロジェクトと、それに対応するJSR、JSR 335、はJava 8がターゲットになります(JSR 336)。
Non-Goals
関数型(function types)の言語機能とgeneral control abstraction*2はJavaへのラムダ式追加の目的ではありません。しかし、将来的にそうした機能追加をしないという意味ではありません。
動機 Motivation
多くの良く使われているオブジェクト指向プログラミング言語で、JVM上で動作するもの(例えば、Grooovy, Ruby, Scala)と仮想マシン上で動作するもの(CLR上のC#)は、クロージャをサポートしています。それゆえに、Javaプログラマーは次第にクロージャをサポートするプログラミングモデルと言語機能に精通するようになりました。
特に興味深いこととしては、クロージャは内部イテレーションのイディオムを可能にします。現在の配列とコレクションは外部イテレーション(external iteration)をサポートしており、これはイテレーションの制御ロジックがトラバースされるデータ構造の外側に存在*3しています。たとえば、配列かコレクションをfor
でループ処理するのは外部イテレーションの一例です。Javaのfor
ループセマンティクスは、厳格な順次イテレーション(strict serial iteration)を命じます。この意味は、プログラマが標準コレクションをイテレーションする方法について、すべての利用可能なコアの使用が許可されていない、ということになります。
内部イテレーションでは、データ構造に実行用のコード片がラムダ式として渡され、データ構造が計算のパーティショニングと結果出力の責任を負います。データ構造は自身の内部的な詳細を知っているので、以下のようなオプションによって計算にとってより良いスケジューリングが選択できる可能性が発生します。
- 実行順序の入れ替え(Alternate execution order)
- スレッドプールを使用したコンカレント実行
- パーティショニングとwork stealing*4を使用したパラレル実行。Java SE 7で追加されるfork/join frameworkは、パラレル実行フレームワークの候補の一つであり、コア数の広範囲で動作するperformance-robustなパーティショニングを提供します。
内部イテレーションスタイルのプロトタイプ例としては、下記のようなfilter-map-reduce操作のシーケンスとなります。
int maxFooWeight = collection.filter( /* isFoo述語を指定する */) .map( /* ラムダ式でFooのweightをmapする */) .max(); /* reduceする */
ラムダ式とは、要求される操作を表現するための簡潔なシンタックスによる、式です。このスタイルは、コレクションの順序付イテレーションを不必要に拘束しがちな、一つ以上の明示的なfor
ループの代わりとなるものです。加えて、良く練られたアルゴリズムは、パラレルな操作セットの実行だけでなく、三つの操作を単一のパラレルパスに集約可能です。
Project Lambdaはまた、仮想拡張メソッドも含んでいます。これは、ソース互換性の懸念のために、広く使われているインタフェースにメソッドを追加することが出来ない長年の制限に対処するものです。
拡張メソッドを、java.util.Collection
とjava.util.List
のような、既存のコレクションインタフェースに加えることにより、それらの型の既存実装で新しいプログラミングイディオムを使用可能になります。JDK(等)のそれらの型の実装は、高パフォーマンスもしくは他の特殊実装を提供するために、スーパーインターフェースの拡張メソッドのデフォルト実装をオーバーライド可能です。
説明 Description
進行中のOpenJDKのProject Lambdaページと対応するJSRが、この取り組みの詳細に関する最新の情報を掲載しています。
全体的なProject Lambdaの取り組みによって影響を受けるプラットフォームのコンポーネントは以下のようなものになります。
- Javaプログラミング言語の仕様
- Java仮想マシンの仕様
- 言語の参照実装の
javac
における変更 - ラムダ式と仮想拡張メソッドのコンパイルサポートのためのクラスファイル変更
- (可能性:Possible)ラムダ実行改良のためのJVM拡張
- 仮想拡張メソッドサポートのためのJVM変更
- 仮想拡張メソッド追加のためのコアAPI変更
- ラムダ式の使用サポートのためのコアAPI変更
- 新しい拡張メソッド使用のためのJDKライブラリ修正
- ラムダと拡張メソッドの関連情報を扱うための、コアリフレクションと
javax.lang.model
のようなリフレクションAPI修正 - 新しいJVM属性を扱うための、
javap
とpack200
/unpack200
のようなクラスファイルツール修正 - (可能性)IIOPシリアライズを含む、シリアライズの修正
- ラムダを使用可能なインタフェースを示すためのjavadocの拡張
- ラムダ式と仮想拡張メソッドの変換をサポートするための
java.lang.*
の言語ランタイム
代替案 Alternatives
straw-man提案で開始されたProject Lambdaと、"ラムダの軌跡"イテレーションを辿ることにより、プロジェクトのシンタックスと機能セット両方が発展してきました。
Project Lambdaのラムダ式部分に関する研究はこれまでに数々の努力が知られており、下記がすべてではないですがその一部です。
Project Lambdaの機能セットは、それ以前の提案よりも、Javaプラットフォームを改善するニーズに取り組むという、ベターな選択をしました。
仮想拡張メソッドの設計も同様に、プログラミング言語コミュニティにおいて従来から多くの研究が知られています。例えば、
- C++の多重継承
- 静的なC#の拡張メソッド
- Fortressのtrait
- Scalaのtrait
- Strongtalkのmixin
他の言語環境と比較すると、Java言語は常に予測可能なセマンティクスを持ってきました。それは、既知のサイズである組み込みプリミティブタイプ、厳密な位置でスローされる例外、厳密に定義されている式の実行順序、など。自動パラレル化(auto-parallelization)を許可するために、組み込みfor
とwhile
ループのセマンティクスを緩めることは、望ましく無く、マルチコアサポートの目的を達成するのに十分でもない、と判断されました。
テスト Testing
ユニット/リグレッションテストに加えて、新言語機能のJCKテストも開発されるでしょう。
機能のユーティリティーも、JDKプラットフォームライブラリでの使用を通して検証されます。
リスクと仮定 Risks and Assumptions
巨大な取組がプラットフォームの多くの側面に影響を及ぼすので、予期せぬ複雑な事態や相互作用が発生する可能性があります。
複数回のイテレーション計画および計画の早期開始をすることで、たとえば、サポートライブラリの開発などにより、複雑な事態のインパクトは軽減されるべきです。
依存性 Dependences
ラムダ式の現在推奨される実装方法は、invokedynamic
とJSR 292で導入されたメソッドハンドル(method handles)に、依存しています。それゆえ、ラムダの許容パフォーマンスは、メソッドハンドルとその他の要因の許容パフォーマンスに依存します。
JEP 107と109のライブラリ動作と言語機能間でのフィードバックが予想されます。
インパクト Impact
- 他のJDKコンポーネント:他のJDKコンポーネントのインパクトは説明(Description)の項目で要点を説明しました。
- 互換性:仮想拡張メソッドはinterfaces.add仮想拡張メソッドによるソース互換性改良を許可することを目的としています。
- セキュリティ:セキュリティ・レビューがラムダのランタイム実装の領域において必要とされます。
- パフォーマンス/スケーラビリティ:ラムダフレンドリーなイディオム VS 伝統的なイディオム、は記録されるべきでしょう。
- ドキュメント:ユーザーガイドとサポートドキュメントを作成する必要があります。
- TCK:大きなプラットフォーム機能なので、言語とライブラリTCKを開発する必要があります。