简体   繁体   English

如何使用模式匹配案例类中声明的变量?

[英]How to use variable declared in pattern-matching case class?

I have the following trait: 我具有以下特征:

sealed trait Tr

case class Test1(str: String) extends Tr

Now I want to use str in my code. 现在,我想在代码中使用str

val tr: Tr = //...

tr match {
    case Test1(str) =>
        val str = //str declared in Test1(str) + "some another string"
}

Is it possible to directly refer to the str preserving the name str . 是否有可能直接引用str保留名称str I can use something like 我可以使用类似

tr match {
    case test1 @ Test1(str) =>
        str = test1.str + "some another string"
}

But this seems ugly to me. 但这对我来说似乎很丑。

str is immutable. str是不可变的。 Try another variable. 尝试另一个变量。

If you want to edit a case class try: 如果要编辑案例类,请尝试:

val test2 = test1.copy(str = test1.str + "some another string")

This will create a new instance, not mutate the case class . 这将创建一个新实例,而不会使case class突变。

You don't need the email operator: 您不需要电子邮件运营商:

sealed trait Tr
case class Test1(str: String) extends Tr
val tr = Test1 ("foo")
tr match {
   case Test1 (str) => println (str) 
}
foo

Of course, reassignment to str isn't possible. 当然,不可能将其重新分配给str。

Note, that in most cases, the parameter of a class has a meaning, and in an ideal world, one of few best meanings, so the stimulus, to repeat the same variable name is high. 请注意,在大多数情况下,类的参数具有含义,并且在理想情况下,为数不多的最佳含义之一,因此重复相同变量名的刺激很高。 But in principal, you aren't bound to use str again. 但原则上,您不必再次使用str。 Maybe the new context provides a better name: 也许新的上下文提供了更好的名称:

tr match {
   case Test1 (bar) => println (bar) 
}

The parameter name, whether 'str' or 'bar' is used to deconstruct the Ctor-call to Test1, and is binding, what fits, to the new name. 参数名称(无论是“ str”还是“ bar”)用于解构对Test1的Ctor调用,并且将适合的名称绑定到新名称。

Note, that in your example: 请注意,在您的示例中:

tr match {
    case test1 @ Test1(str) =>
        str = test1.str + "some another string"
}

If you happen to need to refer to the whole thing, the name tr is in scope, so you might refer to it: 如果您碰巧需要引用整个内容,则名称tr在范围内,因此您可以引用它:

tr match {
    case Test1 (str) => dedodulute (tr)
}

You aren't obliged to use str on the right hand side at all. 您完全没有义务在右侧使用str

Sometimes you even like to refer to the parameter of your case class on the left hand side of the case statement: 有时,您甚至希望在case语句的左侧引用您的case类的参数:

tr match {
      case Test1 (s) if (s.startsWith ("f"))  => println ("foo") 
      case Test1 (s) if (s.startsWith ("b"))  => println ("bar") 
      case _ => println ("unknown") 
}

You may even pick a single element from a list, but have to know it's position from left: 您甚至可以从列表中选择一个元素,但必须从左知道它的位置:

val l = List (4, 1, 3, 9) 
l match {
      case List (_, a, _*) => println ("2nd el is " + a) 
      case _ => println ("unknown") 
}

You can't use 你不能用

case List (_*, a, _) => println ("2nd last el is " + a) 

But you may use literal values, to tighten your match: 但是您可以使用文字值来加强匹配:

l match {
    case List (3, a, _*) => println ("2nd el is " + a + "after 3") 
    case List (4, a, _*) => println ("2nd el is " + a + "after 4") 
    case _ => println ("unknown") 
 }

You can do something like this: 您可以执行以下操作:

sealed trait Tr

case class Test1(str: String) extends Tr

val tem = Test1 ("I am immutable!!")
val str = tem match {
case Test1 (str) => str + "But you can assign me to something else :)."
}

println(str)

Your last case looks almost what you need: 您的最后一种情况几乎满足您的需求:

tr match {
  case test1: Test1 =>
    val str = test1.str + "some another string"
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM