Scala匹配问题+;范围
给定以下代码:Scala匹配问题+;范围,scala,pattern-matching,Scala,Pattern Matching,给定以下代码: case class ChangeSet(field:String, from:Object, to:Object) private var changed:List[ChangeSet] = Nil def change(field:String, from:Object, to:Object) { changed.find{ case ChangeSet(field,_,_) => true } match { case Some(ChangeSet(f
case class ChangeSet(field:String, from:Object, to:Object)
private var changed:List[ChangeSet] = Nil
def change(field:String, from:Object, to:Object) {
changed.find{ case ChangeSet(field,_,_) => true } match {
case Some(ChangeSet(field,to,_)) => // do stuff
case Some(_) => // do stuff
case _ => // do stuff
}
}
给我带来麻烦的一行是Some(ChangeSet(field,to,u))
它可以编译,但似乎正在发生的是Scala将其作为通配符的占位符填充。我的假设基于这样一个事实:当我执行以下Some(ChangeSet(field,to,to))
时,我得到的错误to已经定义为value
我想要的是从方法参数中创建一个带有到的变更集对象
这可能吗?在这样的模式中不能使用变量名。您必须首先将其与新变量匹配,然后进行显式比较
def change(field:String, from:Object, to:Object) {
changed.find{ case ChangeSet(f,_,_) => field == f } match {
case Some(ChangeSet(f,too,_)) if f == field && to == too => // do stuff
case Some(_) => // do stuff
case _ => // do stuff
}
}
如果在模式匹配中使用小写名称,Scala将填充该值。如果只希望在具有该值时匹配,则需要使用大写名称。撇开你试图做的事情的逻辑和名字顺序的可疑变化不谈,你想要:
def change(Field: String, from:Object, To: Object) {
changed.find{
case ChangeSet(Field,_,_) => true
case _ => false // You need this line! No match is an exception, not false!
} match {
case Some(ChangeSet(Field,To,_)) => // do stuff
case Some(_) => // do stuff
case _ => // do stuff
}
}
模式匹配时,Scala将所有以小写字母开头的标识符解释为占位符并填充值。要告诉Scala将To
用作外部作用域中的常量值,需要在其周围加上反勾:`To`
。或者,您可以按照Rex Kerr的建议将的名称改为
改为改为
,但我更喜欢将变量保持小写
这应该起作用:
def change(field:String, from:Object, to:Object) {
changed.find{ case ChangeSet(`field`,_,_) => true } match {
case Some(ChangeSet(`field`, `to`, _)) => // do stuff
case Some(_) => // do stuff
case _ => // do stuff
}
}
这里似乎有两种混淆。第一个是雷克斯和金姆确认的。有关更多信息,请阅读Scala中的编程。归结起来是:
x match { case Some(foo) => } // variable pattern, defines and binds variable foo
x match { case Some(Foo) => } // constant pattern, based on val Foo
x match { case Some(`foo`) => } // constant pattern for lowercase val
也可以使用防护装置约束匹配
x match { case Some(foo) if condition => }
第二个困惑是,您想要“使用方法参数创建变更集对象”。如果我理解正确,您正在尝试使用case类语法构造对象:
ChangeSet(field, from, to)
这在模式匹配的这一方面不起作用。在模式匹配的案例侧发生的事情实际上可以看作是变更集构造的反向<代码>匹配{case ChangeSet(field,from,to)=>}
这类解构ChangeSet
对象并将其部分分配给字段
、from
和to
VAL。当它这样组合时也是如此:Some(ChangeSet(field,from,to))
,它首先解构Some
,然后解构ChangeSet
。您可以看到,在利用相同的解构机制时,对值定义进行处理:
scala> val cset = ChangeSet("a", "from", "to")
cset: ChangeSet = ChangeSet(a,from,to)
scala> val Some(ChangeSet(s, o1, o2)) = Some(cset)
s: String = a
o1: java.lang.Object = from
o2: java.lang.Object = to
似乎您要做的是构造一个新对象,复制变更集的值,但替换单个字段。案例类通过copy
支持这一点,继续我的REPL示例:
scala> val cset2 = cset.copy(from = o2)
cset2: ChangeSet = ChangeSet(a,to,to)
考虑到这一点,这里有另一个关于更改的建议:
def change(field:String, from:Object, to:Object) {
changed.find(_.field == field) match {
case Some(cset) =>
val csetnew = cset.copy(from = to)
// do stuff with csetnew
case None =>
// do stuff
}
}
这并不完全正确:您可以使用backticks符号,如中所示。我不知道;至少在两年多以前:-)使用backticks符号最棘手的部分是如何让它正确地显示在StackOverflow答案中:-)