是否可以将保护条件与密封案例类声明中的模式匹配相结合?
我意识到可以在匹配区块中包含保护条件,但我觉得在密封的案例类中预先定义这些条件是有益的。 这将允许开发人员定义严格的可能输入集,编译器在模式匹配时将检查这些输入。
总而言之,我希望能够做到这样的事情:
// 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
}
}
答案 0 :(得分: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))
答案 1 :(得分:-1)
我不相信您将能够在Scala中编译时检查一般约束/断言,因为Scala没有执行此操作所需的static verifier。如果您有兴趣,请查看(研究)语言/工具,例如ESC/Java,Spec#,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.
*/
但这可能不是你想到的。