16

私は最近Programming Scalaを購入し、それを読んでいます。言語は間違いなく私が期待したものではありません! 具体的には、Lisp マクロと Haskell の型レベルの副作用の分離を除いて、私が知っているほぼすべてのプログラミング言語のアイデアを実装しているようです。

率直に言って、それは私をやや圧倒しています。非常に多くのツールを自由に使用できるのは良いことだとは思いますが、実際には JVM で厳密に型指定された関数型言語を探していました。おそらくそのようにScalaを使用できると思いますが、ライブラリとやり取りしたり、他の誰かのコードを調べたりすると、この高度な(私にとって)OOPの多くに遭遇することになると思います--特性と「オブジェクト階層」線形化」、このすべての抽象的でオーバーライドするビジネス、シングルトン、パッケージ、およびコンパニオン オブジェクト、暗黙の変換...さまざまな構文のショートカットやシュガーは言うまでもありません。

多くの正当な理由から、ある言語のスタイルを別の言語に押し込もうとするプログラマーを嘆く人がよくいます。しかし、すべての言語が Scala のようにマルチパラダイムであるとは限らないため、おそらく Scala のコミュニティは異なる見解を持っているのではないでしょうか? 例えばF#では、プログラミングスタイルやOOPの使用量に多少の余裕があるようです。しかし、読んだだけでは、これが Scala にとっても良い哲学であるかどうかはわかりません。

経験豊富な Scala プログラマーがここで私を助けてくれますか? わかりやすくするために編集:基本的に、高度な OOP 側について心配することなく、Scala の FP 機能のみ (またはほとんど) を安全に使用できますか?

とりとめのない質問でごめんなさい!

4

4 に答える 4

16

あなたが見ていることの 1 つは、Scala がとりわけJVM 上の強く型付けされた関数型言語であることです。

Scala は単なる関数型言語ではありません。最初は 1 つ (Funnel: http://lamp.epfl.ch/funnel/ ) でしたが、Java クラスとの強力な相互運用性を実現するという明確な目標を持って、オブジェクト指向言語に拡張されました。

抽象化、オーバーライド、およびパッケージはすべて、この相互運用性の実際の例です。


残りは新機能ではなく、単に Java から制限を取り除くものと見なされるかもしれません。それらを 1 つずつ取り上げます。

特性とオブジェクト階層の線形化

Java インターフェースに抽象メソッドのみを含めることができるという制限を取り除きます。線形化は、Scala がそれ以外の場合に発生するダイヤモンド継承の問題を解決する方法です。

シングルトン

Java の静的メソッドは、その C++ 構文の遺産の名残りであり、C との相互運用に必要な手続き型スタイルをより適切にサポートするために追加されました。? )

コンパニオン オブジェクト

特権アクセス権を使用して、静的メソッドの代わりにシングルトンを使用できるようにします。

暗黙の変換

Java はすでにこれを行っていますが、式 のように、オブジェクトとプリミティブを文字列に暗黙的に変換するだけに制限されています"" + 3。Scala はこのアイデアを拡張し、プログラマが他の変換に使用できるようにします。

于 2010-11-22T16:59:30.497 に答える
8

ケビンの答えにいくつかコメントを追加さ​​せてください。

トレイトは主に抽象化(大まかに言えば、Haskell型クラスが抽象化を定義するのと同じ方法)およびミックスインとして使用されます。したがって、私のコードはMapトレイトを使用している可能性がありますが、実際にはHashMapのようなタイプのインスタンスを使用しています。逆に、「サービス」タイプにロギング機能を持たせたい場合は、再利用可能なロギング特性を組み合わせることができます。

幸い、単純な場合を超えて線形化アルゴリズムについて考える必要はほとんどありません。たとえば、メソッド呼び出しをインターセプト(ラップ)して、メソッドが呼び出されたという事実をログに記録する特性を組み合わせることができます。アルゴリズムは、より複雑な線形化のケース(本で示す例のように)を処理する必要がありますが、実際には、そのような複雑なタイプは貧弱な設計です、IMHO。

特別なサブセットコンパニオンオブジェクトを含むシングルトンは、すべてをオブジェクトにするように設計されていますが、関数と場合によってはいくつかの状態をラップする名前空間として表示することもできます。

少し「魔法」の場合、暗黙の変換は非常に便利です。Haskell型クラスをシミュレートするためにそれらがどのように使用されるかを確認すると役立つ場合があります。これがDebasishGhoshによる素晴らしい投稿です:http://debasishg.blogspot.com/2010/06/scala-implicits-type-classes-here-i.html

于 2010-11-22T18:00:38.837 に答える
7

この質問には確かに確かな点があると思います。これは、ライブラリが例外を処理する方法を調べることで明らかになります。

Java ライブラリを操作すると、どのメソッドも例外をスローする可能性があります。これは、チェックされた例外を介して明示的に行うことも、ランタイム例外を介して (API の観点から) 透過的に行うこともできます。Either失敗を示すために、より機能的な型 (またはscalazの)を使用しようとしている可能性のあるプログラマーとして、これについてどうすればよいでしょうValidationか?

これが scala でどのように実行されるか (つまり、問題にアプローチし、純粋に機能的なアプローチを選択する) は、私にはまったく明確ではありません。確かに、さまざまなスタイルのコーディングが作成される可能性があります。そうは言っても、scala の機能面に沿って選択できる豊富で便利なものはたくさんあります。そして、プログラム内で関数型コードと命令型コードをこのように組み合わせて、相互に連携させることは確かに可能です。もちろん、機能的純粋主義者は、これが最適な状況であるかどうかについて意見が分かれるかもしれません。

それだけの価値はありますが、プログラム内に機能パラダイムを適用することで、コードが際限なく改善されることがわかりました。HaskellF#も試したことがないので、最終的な結果が良いか悪いかはわかりません。

しかし、それはJavaで床を一掃します。JVMでそれを取得する(すべての Java ライブラリと共存できるという実際的な利点がある) ことは、私の観点からすると、キラー アプリです。


エッジでは、scala の関数側を使用し始めると、多くの問題に遭遇することになります。これらは最も明白です:

  • 暗黙的な関数のカリーA => B => C化の欠如 (つまり、との同等性(A, B) => C)
  • 暗黙的な関数のタプルの欠如(つまり、n 項関数と、n 項タプルをパラメーターとして取る 1 項関数との間の同等性)
  • 部分的に適用された型コンストラクターの推論の欠如 (つまり、との等価性、M[A]たとえばEither[Int, A])

これらの問題は両方とも、きれいで明確な機能コードであるべきものを、見苦しく曖昧なものにしてしまいます。

于 2010-11-23T00:04:27.020 に答える
3

私はscalaでプログラミングを始めましたが、scalaコミュニティの経験豊富なメンバーではありません。しかし、私は長い間、別の言語であるpythonを使用してきましたが、Pythonは、それほどではありませんが、同様の状況にあります。手続き型、オブジェクト指向、機能的なスタイルをサポートします。一部の人々は1つの極端に固執する傾向がありますが、多くの人々は異なるスタイルの構成を組み合わせていることがわかりました。したがって、慣用的なpythonは、リスト内包表記、ファーストクラス、高階関数、および部分関数を多用することで構成されます。これらの関数が機能するデータはオブジェクトです。ただし、長年にわたって、機能にわずかにシフトする傾向があることに注意してください。

Scalaがサポートするスタイルの包括性を考えると、問題を解決する正しい方法は1つもない可能性が高いと思います。しかし、極端なものの1つに固執したいプログラマーに寛容であるにもかかわらず、プログラマーの大部分がゆっくりと両方を賢明に使用するスタイルに向かう傾向があることを見て驚かないでしょう。

于 2010-11-22T17:57:26.753 に答える