7

封印されたケースクラス宣言内でガード条件とパターンマッチングを組み合わせることができますか?

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

要約すると、私は次のようなことと同等のことを実行できるようにしたいと思います。

// 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
    }
}
4

2 に答える 2

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))
于 2012-08-11T15:29:13.410 に答える
-1

Scala には、これを行うために必要な静的ベリファイアがないため、コンパイル時にチェックされる一般的な制約/アサーションを Scala で使用できるとは思いません。興味があれば、ESC/JavaSpec#DafnyVeriFastなどの (研究) 言語/ツールをご覧ください。

型レベル プログラミングまたはScala マクロを使用して、通常のコンパイラ 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.
   */

しかし、それはおそらくあなたが考えていたものではありません。

于 2012-08-11T12:36:16.743 に答える