web-dev-qa-db-ja.com

C#、JavaおよびScala to Closures / Lambdas / ...)のアプローチの利点と欠点は何ですか?

C#とScalaの技術的な実装の違いは何であり、両方のソリューションは実装のアイデアとどのように比較され、電子メールで発声された懸念事項と比較しますか Peek Past lambda Brian Goetzにより、 Project Lambda(JSR 335) のメーリングリストに送信されましたか?

メールから:

「たぶんラムダは内部クラスのインスタンスであるべきだ、それは本当に簡単だろう」という道を探りましたが、最終的には「関数は言語の将来にとってより良い方向である」という立場に達しました。

そしてさらに:

ラムダはオブジェクトであるという世界観は、この可能な未来と矛盾しています。 lambdas-are-functionsの世界観はそうではなく、この柔軟性を維持することは、ラムダにオブジェクトらしさの外観さえも負担させないことを支持する点の1つです。

結論:

Lambdas-are-functionsが扉を開きます。 Lambdas-are-objectsはそれらを閉じます。
これらのドアを開いたままにすることをお勧めします。

Redditスレッド 上の人からのコメントには、

私は実際にこれについてメールし、彼の説明に関する私の限られた理解にC#と現在のJava設計はデリゲートが実際にはオブジェクトであり関数型ではないという点で非常に似ています。彼はJavaはC#のラムダのデメリットから学び、それらを回避する必要があると信じています(C#がJavaのデメリットから学び、最初にそれらを回避したように)。

「Lambdas-are-functions」アプローチが「Lambdas-are-objects」よりも将来の機会を増やすのはなぜですか?誰かが存在する違いと、それらがコードの記述方法にどのように影響するかを説明できますか?

Scala "動作するだけ"にあることを見て、C#/ Java(8)で採用/提案されたアプローチについて何か不足していると思い続けます。おそらくそれは後方への懸念に関連しています-互換性?

30
soc

オブジェクトと関数についての議論は赤のニシンだと思います。質問が「ラムダは関数ですか、それともオブジェクトですか?」答えはyesである必要があります。

それが、ファーストクラスの関数のポイントです。これらは、他の型とは異なる方法で処理されません。 Javaは、すでにオブジェクトタイプとプリミティブタイプの違いをほとんど無視しています(そしてScalaはさらに優れています)。そのため、ラムダがオブジェクトのサブクラスであるか、新しいプリミティブ型などは、言語にとってそれほど重要ではありません。重要なのは、ラムダをコレクションに入れ、それらを渡して呼び出し、それらを呼び出し、その他のいずれかを実行できることです。オブジェクトまたはメソッド。

Scalaは、()だけで呼び出せるapplyというメソッドを持つラッパーオブジェクトを使用してこれを実現し、メソッド呼び出しのように見せます。これは見事に機能します。ほとんどの場合、メソッドがあるのか​​、関数オブジェクトの適用を呼び出しているのかを気にする必要さえありません。

15
Rex Kerr

私が理解していることから、それはラムダが第一言語レベルでどのように考えられるであるかについての詳細です。メールが言うように、

現在のデザインはラムダ(SAMタイプ)のオブジェクトボックスに密接に結びついていると思うかもしれません。しかし、これは表面から注意深く隠されているので、将来、「裸の」ラムダを検討したり、ラムダの他の変換コンテキストを検討したり、ラムダを制御構造にさらに厳密に統合したりできます。現在はそうしておらず、そのための具体的な計画もありませんが、将来的にそれを実行できる可能性は、設計の重要な部分です。

私はあなたの質問をかなりうまくまとめていると思います。 「ラムダはオブジェクトである」と宣言した場合、それらは特定のクラスのオブジェクトにすぎず、それで行き詰まります。一方、「ラムダは関数である」と宣言した場合、意味論的にの方がはるかに豊かなプレイフィールドになります。 Java 1.7はそれらをオブジェクトにコンパイルする可能性があるため、その時点では実質的に同じです。

しかし、Java 1.8または1.9は、関数をより柔軟な方法で使用できるようにするよりも、具体化された構造型など)言語に変更をもたらす可能性があります。「ラムダがオブジェクト」である場合、これらは変更には下位互換性がなく、人々の既存のコードを壊さないように、新しいコンセプトをすべて導入する必要があります。ただし、javacがラムダを静かにオブジェクトの背後に静かに変換している場合、新しいjavacは、セマンティクスが保持されている限り、必要なものに変換できます。

9
Andrzej Doyle

ほとんどの場合、彼はすぐに何かにコミットしたくありません。彼が提示した消去を超える理由は見当たりませんが、それは確かに非常に強い理由です。

私は関数型が好きではありません-関数型が大好きです-しかし、その関数型はJava型システムの既存の側面、消去とうまく戦えません。消去された関数型は両方の最悪です世界。

ScalaのRegexでこれらのメソッドを検討してください:

def replaceAllIn (target: CharSequence, replacer: (Match) ⇒ String): String
def replaceSomeIn (target: CharSequence, replacer: (Match) ⇒ Option[String]): String

彼らが単にこれであるならば、それはより単純でしょう:

def replace (target: CharSequence, replacer: (Match) ⇒ String): String
def replace (target: CharSequence, replacer: (Match) ⇒ Option[String]): String

残念ながら、これらの2つの関数(同一)が消去されているため、これは不可能です。ただし、これらの関数はやや異なることをするので、別の名前で十分かもしれません。

ただし、Matchは非常に便利ですが、ほとんどの場合、一致するStringまたはサブグループのリストのいずれかが必要です。これが必要です:

def replaceAllIn (target: CharSequence, replacer: (String) ⇒ String): String
def replaceAllIn (target: CharSequence, replacer: (Seq[String]) ⇒ String): String
def replaceAllIn (target: CharSequence, replacer: (Match) ⇒ String): String

消去のため不可能。私は直接この問題に関与したため、この特定の例を選択しましたが、この正確な問題が原因で、過負荷が違法である理由を人々が尋ねるStack Overflowで少なくとも半ダースの質問を見てきました。

そして、ScalaのパターンマッチングとJavaのinstanceofは、消去のために事実上役に立たないと考えてください。

この問題が処理されるまで関数タイプを遅らせるのは公平だと思います。結局のところ、JVMで使用できる言語はたくさんあり、Javaは急速に進化している言語のようではありません。

5