2012-08-11 3 views
7

密閉ケースクラス宣言内でガード条件とパターンマッチングを組み合わせることは可能ですか?Scala:密封されたケースクラス宣言の中でガード条件とパターンマッチを組み合わせることはできますか

マッチブロック内にガード条件を含めることは可能ですが、この条件を密封されたケースクラスの前に定義することは有益でしょう。 これにより、開発者はパターンマッチングの際にコンパイラがチェックする可能な入力の厳密なセットを定義できます。

だから、要約すると、私はこのようなものと同等のものを行うことができるようにしたい:

// create a set of pattern matchable cases with guards built in 

sealed abstract class Args 
case class ValidArgs1(arg1:Int,arg2:Int) if arg1>1 && arg2<10 extends Args 
case class ValidArgs2(arg1:Int,arg2:Int) if arg1>5 && arg2<6 extends Args 
case class InvalidArgs(arg1:Int,arg2:Int) if arg1<=1 && arg2>=10 extends Args 


// the aim of this is to achieve pattern matching against an exhaustive set of 
// pre-defined possibilities 

def process(args:Args){ 
    args match 
    { 
     case ValidArgs1 = > // do this 
     case ValidArgs2= > // do this 
     case InvalidArgs = > // do this 
    } 
} 

答えて

-1

私はあなたがでチェックされている一般的な制約/アサーションを持ってできるようになることを信じていません。 Scalaのコンパイル時には、これを行うために必要なstatic verifierがないためです。興味があれば、ESC/JavaSpec#DafnyまたはVeriFastのような(研究の)言語/ツールを見てください。

type-level programmingまたはScala macrosを使用して、通常のコンパイラScalaで非常に限られた量の静的検査を行う方法があるかもしれませんが、私はそれらのどちらかに慣れていないので、これは私のものです。正直言って、マクロが実際にここで助けてくれるのであれば、私はかなり驚くはずです。

どのように動作するのかは、ランタイムアサーションのチェックです。

case class Foo(arg1: Int, arg2: Int) { 
    require(arg1 < arg2, "The first argument must be strictly less than " + 
         "the second argument.") 
} 

Foo(0, 0) 
    /* java.lang.IllegalArgumentException: requirement failed: 
    *  The first argument must be strictly less than the second 
    *  argument. 
    */ 

しかし、これはおそらくあなたが心に留めたものではありません。

+0

提案された機能には、既にスケーラがもう必要ありません。これは単なる構文砂糖です。 – ayvango

+0

@ayvango Scalaは静的検証をサポートしていません。あなたは何を意味するのですか、なぜダウンボートですか? –

+0

トピックスターターは静的検証を必要としません。彼はちょうど提供されたヒントでunapplyメソッドを拡張したい。 – ayvango

6

+1興味深い投機的な質問です。タイプレベルで操作していないので、コンパイル時にインスタンス化を確認することはできません。コンストラクタにリテラルを渡しているとき。

一方、シナリオ(パターンマッチング)は実行時アクションです。そのためには、ケースクラスの代わりに抽出機能を使用することができます。

case class Args(arg1: Int, arg2: Int) 
object ValidArgs1 { 
    def apply(arg1: Int, arg2: Int): Args = { 
    val res = Args(arg1, arg2) 
    require(unapply(res)) 
    res 
    } 
    def unapply(args: Args): Boolean = args.arg1 > 1 && args.arg2 < 10 
} 

def process(args: Args) = args match { 
    case ValidArgs1() => "ok" 
    case _   => "invalid" 
} 

process(ValidArgs1(2, 9)) 
process(Args(1, 10)) 
process(Args(3, 4)) 
+0

これは完璧なおかげで、遅く返事を申し訳ありません! – newlogic

+0

実際に私はそれがほぼそこにあると思うかもしれませんが、ケースクラスに適用および適用解除メソッドを追加して封印して、コンパイル時のチェックを行い、タイプの実行パスをマップします。適用/未適用条件が満たされている場合の経路 – newlogic

関連する問題