クロージャー
導入
クロージャは、基本言語の便利な拡張機能です。これらはコードをより簡潔にするだけでなく、プログラミングの関数型パラダイムの領域を通過するための手段として使用できます。プログラムでは、関数を第一級オブジェクトとして扱うことができます。変数に格納したり、引数としてメソッドに渡したり、メソッドや関数に他の関数を返させたりすることができます。MPS クロージャサポートを使用すると、自国語でクロージャを使用できます。実際、MPS 自体は、たとえばコレクション言語でクロージャを多用します。
この言語は、Java のクロージャに関する「BGGA」提案仕様に大まかに従っており、Java のラムダよりも強力です。MPS クロージャは、次の 4 つの非互換性を回避することを条件に、Java ラムダに生成されます。
歩留まり操作
「機能的な」抽象クラス
アノテーション
親スコープと競合するローカル変数
それ以外の場合、クロージャは匿名の内部クラスに生成されます。生成されたソリューションのクラスパスに存在する必要があるのは、クロージャランタイム jar ファイルのみです。
機能タイプ
{ Type1, Type2... => ReturnType }
関数型宣言の簡単な例から始めましょう。パラメーターを受け入れず、値を返さない関数を宣言しています。
サブタイプ規則
関数型は戻り型によって共変であり、パラメーター型によって反変します。
例: 与えられた {String => Number} を受け入れるメソッドを定義しました:
このメソッドに {Object => Integer}(Object を受け取り int を返す関数)のインスタンスを渡すことができます。
簡単に言うと、スーパー型のシグネチャーで約束された約束を守る限り、さまざまな実型のパラメーターと戻り値を使用できます。
Closure リテラル
Closure リテラルは、次の構造を入力するだけで作成されます: { <parameter decls> => <body> }。「new」演算子は必要ありません。
結果のタイプは、これらの規則の 1 つ以上に従って計算されます。
ExpressionStatement の場合は最後のステートメント。
式を含むステートメントを返します。
利回りステートメント。
注: 単一のクロージャーリテラル内で return と yield を組み合わせるのは不可能です。
Closure の呼び出し
クロージャで呼び出すことができるメソッドは、invoke 操作だけです。入力する代わりに
クロージャーを呼び出すには、この操作を単純化したもの(パラメーターリストを囲む括弧)を使用することをお勧めします。
クロージャを起動すると、通常のメソッド呼び出しのようになります。
クロージャリテラル定義の例
再帰
再帰のない関数型プログラミングは水なしでコーヒーを作るようなものなので、クロージャの本体内からクロージャを再帰的に呼び出す自然な方法があります。
クロージャーの本体内のスタンドアロン呼び出しは、現在のクロージャーを呼び出します。
Closure 変換
実用的な目的のために、単一メソッドインターフェースのインスタンスが期待される場所でクロージャリテラルを使用することができ、またその逆も可能です。
生成されたコードは、無名クラスを使用したときとまったく同じです。
Java が Runnable、Callable、またはさまざまなオブザーバーまたはリスナークラスのインスタンスを必要とするすべての場所について考えてみてください。
インターフェースと同様に、厳密に 1 つの抽象メソッドを含む抽象クラスもクロージャリテラルから適応させることができます。これは、たとえば、関数として機能する既存のインターフェースを新しいインターフェースを実装する抽象クラスに変更できる場合に、新しい API への円滑な移行に役立ちます。
収量計算書
yield ステートメントはクロージャーがコレクションを生成することを可能にします。クロールリテラルの本体内で yield ステートメントが見つかった場合、その影響は次のとおりです。
yield ステートメント式の型が Type の場合、クロージャリテラルの結果の型は sequence <Type> です。
本体内のすべての制御ステートメントは、生成時に無限の do-while ループ内で switch ステートメントに変換されます。
return 文の使用は禁止されており、最後の ExpressionStatement の値は無視されます。
関数を返す関数
そこに機能的な心のための関数型プログラミングの少し:
curry() メソッドは次のように定義されています。
ランタイム
クロージャ言語によって生成されたコードを実行するには、ソリューションのクラスパスにクロージャランタイムライブラリを追加する必要があります。この jar ファイルには、関数型の変数と一部のユーティリティクラスをサポートするために必要な合成インターフェースが含まれています。それはに位置しています: %MPS_HOME%/core/baseLanguage/jetbrains.mps.baseLanguage.closures.runtime.jar
BGGA 提案との違い
制御フローをいじることはありません。これは、クロージャリテラルの境界を超える制御フローステートメントをサポートしていないことを意味します。
「早期 return」の問題はありません。MPS を使用すると、return を体内の任意の場所で使用できるようになります。
歩留まりステートメント。
[1] Java プログラミング言語用のクロージャ (英語)
[2] BGGA クロージャ仕様のバージョン 0.5 は部分的にサポートされています (英語)
[3] これはもはや真実ではありません。最適化の手段として、インターフェース変換に対するクロージャリテラルのみがサポートされています。
関連ページ:

BaseLanguage のプロパティ
プロパティは、getter および setter とともにプライベートフィールドを使用して BaseLanguage クラスを強化するためのショートカットを提供します。特性の説明:プロパティは BaseLanguage 自体の一部であるため、追加のインポートは必要ありません。これらは、フィールドやメソッドとともにクラスメンバーとして作成されることになっています。プロパティは以下を定義します。可視性。getter の可視性として使用されます。型 - プロパティによって格納される値の型、getter の戻...

コレクションの言語
コレクションのサポートを追加する Base Language の拡張。導入:コレクション言語は、いくつかの最も一般的に使用されるコンテナーの使用を可能にする一連の抽象化と、クエリを構築するための一連の強力なツールを提供します。コレクションによって提供される基本的な型はです。これは、Java の Iterable または .NET の IEnumerable に類似した抽象化です。コンテナーには、(配列ベースとリンクリストの両方)、およびが含まれます。コレクション言語は、LINQ が行うのと同様の...