3

=>徹底的なパターンマッチングは素晴らしいですが、ケース( )演算子の左側でのみ機能するように見えます。

関数(または式)の出力をその列挙にバインドできることを人が確認できる方法があるかどうか知りたいです。目標は、列挙から項目を出力するのを忘れたときにコンパイラーに通知させることです。

私の例では、3つの項目を含む次の列挙を使用します。

object MyEnum { 
    sealed trait t 
    case object E1 extends t
    case object E2 extends t
    case object E3 extends t
}

そして、これがコンパイル時の警告を生成するパターンマッチ式です(すでに知っているように):

def foo( e : MyEnum.t ) : Boolean =
    e match {
        case MyEnum.E1 => true
        case MyEnum.E2 => false
        case MyEnum.E3 => true   // if we leave this line out, we get a warning
    }

MyEnum.E3網羅的ではないパターンマッチングを引用して、パターンマッチング式を省略した場合、Scalaは文句を言います。これは非常に有益ですが、逆のことが可能かどうか疑問に思います。

MyEnum.tの右側のすべてのケースを説明できます=>か?

これを強調する例を次に示します。

def bar( s : String ) : Option[MyEnum.t] = 
    s match {
        case "a" => Some(MyEnum.E1)
        case "b" => Some(MyEnum.E2)
        case "c" => Some(MyEnum.E3)  // if we leave this out, no warning
        case _ => None
    }

この例では、の行を省略した場合MyEnum.E3、コンパイラーは何も問題がないかのように続行します。私が言いたいアサーションは次のとおりです。

forall MyEnum.t (aliased as e) there exists Some(e) | None

これはランタイムテストで簡単にカバーできることは理解していますが、これを静的にチェックする方法があるかどうか知りたいです。

ありがとう。

4

2 に答える 2

0

いいえ、それは不可能です。これは、1936年に解決不可能であることが証明された停止性問題と同等であるためです。

于 2013-02-17T13:36:30.157 に答える
0

私は運を押し上げて、それは不可能だと主張します(これをオーダスキーから秘密にしておきましょう)。Scalaコンパイラがそのような状況を検出できたとしたら、それはすでにあるよりもさらに遅くなると思います;)

私が見ることができる唯一の方法は、あなたが行ったのと同じようにfooを定義し、逆マップを作成するためにfooを反復処理することによってバーを定義することですが、それは私にはあまり意味がなく、特定の場所では機能しない可能性があります場合。

あなたのケースは、単体テストが役立つ場合の非常に良い例だと思います。それでは、単体テストを書いてみませんか?

于 2013-02-04T20:03:25.420 に答える