Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/opencv/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Scala匹配问题+;范围_Scala_Pattern Matching - Fatal编程技术网

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答案中:-)