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 回答