Scalaコンパイラーがシールされていないクラス/トレイトに対してパターンマッチング警告を出せないのはなぜですか?


10

シールtraitまたはabstract classScalaを使用してからパターンマッチングを使用する場合、コンパイラーはこの特定のパターンマッチのコンパイル時に、このトレイト/クラスの可能な実装が何であるかを知りませんか?だから、もしそうなら、可能性のあるすべての依存関係/インポートをチェックすることによって、使用できるタイプを知っているのでtrait/ abstract classがシールされていなくても、パターンマッチの警告を出せないでしょうか?

たとえば、私がに対してOption[A]パターンマッチングを行っているSome[A]が、に対してNoneは行わない場合、Optionはシールされているため、コンパイラは文句を言うでしょう。

コンパイラがそれを認識/解決できない場合、なぜ彼はそれができないのですか?そして、コンパイラーが(理論的に)それを実行できる場合、それがScalaで使用されない理由は何ですか?そのような動作をサポートする他の言語はありますか?


あなたが何を求めているのかは不明です。一致式がすべての可能な入力をカバーしていない場合、コンパイラーが警告を発しますか?おそらく、例があなたの質問をより明確にするでしょう。
kdgregory 2014

2
誰かが新しいサブクラスを導入できる場合、パターンマッチは完全ではありません。例えばあなたは、いくつかの抽象クラスを作るFooサブクラスでAB、とC、とあなたのパターンマッチの全ては、これら3つを一致させます。Dパターンマッチを爆破する新しいサブクラスを追加することを妨げるものは何もありません。
ドヴァル2014

@kdgregoryはい、わかりました。わかりやすくするために例を追加しました。
ヴァレンタリー

3
すべてのインポートをチェックするだけでは、考えられるすべてのサブクラスを見つけるのに十分ではありません。別のサブクラスは、後で実行時にロードされる別のクラスファイルで宣言される場合がありますjava.lang.ClassLoader
アモン

回答:


17

クラスのすべてのサブクラスを計算することはクラス階層分析と呼ばれ、動的コードロードを使用する言語で静的CHAを実行することは、停止問題を解決することと同じです。

さらに、Scalaの目標の1つは、独立したモジュールの個別のコンパイルとデプロイです。そのため、コンパイラーは、クラスが複数のモジュールを決して見ないため、クラスが別のモジュールでサブクラス化されているかどうかを知ることができません。(結局のところ、システムにモジュールが存在していなくても、他のモジュールのインターフェイスに対してモジュールをコンパイルできます!)そのためsealed、すべてのサブクラスを同じコンパイル単位で定義する必要があります。

これは、JVMがC ++コンパイラと非常に有利に競合できる理由の1つでもあります。C++コンパイラは通常、静的コンパイラであるため、メソッドがオーバーライドされているかどうかを概して判断できないため、インライン化できません。JVM OTOHは通常、動的コンパイラーであり、メソッドがオーバーライドされているかどうかを確認するためにCHAを実行する必要はありません。実行時にクラス階層を確認するだけです。そして、プログラムの実行後の時点で、以前にはなかった新しいサブクラスが発生したとしても、大した問題ではなく、インライン化せずにそのコードを再コンパイルするだけです。

注:これはすべてScala内でのみ適用されます。JVMにはの概念がないsealedため、別の言語に通信する方法がないため、別の JVM言語sealedからクラスをサブクラス化することは完全に可能です。プロパティはに記録されたアノテーションが、他の言語のコンパイラは、明らかに、考慮にこれらの注釈を取ることはありません。sealedScalaSig


3

これ(少なくともコンパイル時に既知のすべてのクラスに対して)実行できますが、コストがかかるだけです。他のファイルが変更されるたびに、パターンマッチを含むすべてを効果的に再コンパイルする必要があるため、増分コンパイルを完全に破棄します。

そして、あなたは何を買っていますか?新しい派生クラスが追加されたときに頻繁に変更する必要があるパターンマッチを記述するのはコードの匂いです。開閉の原則違反です。継承を適切に使用すれば、そのようなパターンマッチを記述する必要はありません。そして、はい、オープン/クローズの原則は、クラスベースの継承のない関数型言語にも適用されます。実際、型クラス、マルチメソッド、単純な高階関数などの機能の間では、関数型言語を使用することで、変更なしの拡張がはるかに簡単になります。


1
It can be done (at least for all classes known at compile time), it's just expensive.しかし、プログラムが100%自己完結型ではない場合(つまり、外部.jarファイルに依存している場合)、いずれかのs を使用してコンパイルした、新しいサブクラス忍び込むことはできませんjarか?したがって、コンパイラーは「パターン一致は完全に網羅されていますが、依存関係のいずれかが変更されると変更される可能性があります」と通知する可能性があります
Doval、

したがって免責事項。実際には、依存関係を完全に一致させる必要があるほど強く結合されている場合は、外部またはその他の方法で、とにかく再コンパイルする必要があります。
カールビーレフェルト2014

@Doval次に、何らかの形式の委任を使用し、呼び出されるクラスに何をすべきかを決定させ、制御を反転させる必要があります。これがOOPの目的でした。あなたがそれを望まないなら、あなたには現在の問題があります。
そり2014

@ArtB私は、委任または制御の逆転がこれとどう関係するのかを理解できません。
Doval、

外部から追加できるユーザーと一緒に使用する場合は、クラスを呼び出し、ロジックをそれらのクラスに移動します。
そり2014
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.