scala案例类问题

发布于 2024-08-07 05:11:05 字数 272 浏览 2 评论 0原文

我有两个关于“::”案例类的问题。

:: 可以用作

case head :: tail => ...

它是如何工作的?意思是,Scala 用于将 List 实例与 :: case 类进行匹配的流程到底是什么?鉴于我有一个类 MyClass,带有运算符 op,我可以创建一个名为 op 的案例类,我可以将其用作:

case foo op bar => ....

I have two questions regarding the '::' case class.

:: can be used as

case head :: tail => ...

How does it work? Meaning, what is exactly the flow that Scala uses to match a List instance with the :: case class? Given that I have a class MyClass, with operator op, can I create a case class named op that I can use as:

case foo op bar => ....

?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

倾听心声的旋律 2024-08-14 05:11:05
     scala> abstract class Stack {
     |     def push(n :Int):Stack
     | }
      defined class Stack

     scala> final case class push(st :Stack,hd :Int) extends Stack {
     |     override def push(n :Int):Stack = new push(this,n)
     | }
     defined class push

     scala> object NullStack extends Stack {
     |     override def push(n :Int):Stack = new push(null,n)
     | }
     defined module NullStack

     scala> val s = NullStack.push(1).push(2)
     s: Stack = push(push(null,1),2)

     scala> def test(s :Stack) = s match { case st push i => println(st +"push " + i) }
     test: (Stack)Unit

     scala> test(s)
     push(null,1)push 2
     scala> abstract class Stack {
     |     def push(n :Int):Stack
     | }
      defined class Stack

     scala> final case class push(st :Stack,hd :Int) extends Stack {
     |     override def push(n :Int):Stack = new push(this,n)
     | }
     defined class push

     scala> object NullStack extends Stack {
     |     override def push(n :Int):Stack = new push(null,n)
     | }
     defined module NullStack

     scala> val s = NullStack.push(1).push(2)
     s: Stack = push(push(null,1),2)

     scala> def test(s :Stack) = s match { case st push i => println(st +"push " + i) }
     test: (Stack)Unit

     scala> test(s)
     push(null,1)push 2
↘紸啶 2024-08-14 05:11:05

Scala 编程的第 301 页有详细介绍,关于 List 上的模式匹配s.

“cons”模式x :: xs是中缀的一种特殊情况
运营模式。你已经知道,当被视为一种表达时,
中缀操作相当于方法调用。对于模式,规则
不同之处:当被视为模式时,中缀操作如 p op q
相当于op(p, q)
也就是说,中缀运算符 op 被视为构造函数模式。
特别是,诸如 x :: xs 这样的 cons 模式被视为 ::(x, xs)
这暗示应该有一个名为 :: 的类与该模式相对应
构造函数。确实有这样一个类。
它被命名为 scala.:: ,并且正是构建非空列表的类。

It's detailed in page 301 of Programming in Scala, About pattern matching on Lists.

The "cons" pattern x :: xs is a special case of an infix
operation pattern. You know already that, when seen as an expression,
an infix operation is equivalent to a method call. For patterns, the rules
are different: When seen as a pattern, an infix operation such as p op q
is equivalent to op(p, q).
That is, the infix operator op is treated as a constructor pattern.
In particular, a cons pattern such as x :: xs is treated as ::(x, xs).
This hints that there should be a class named :: that correspond to the pattern
constructor. Indeed there is such a class.
It is named scala.:: and is exactly the class that builds non-empty lists.

梦屿孤独相伴 2024-08-14 05:11:05

实际上, :: 是一个案例类这一事实只解决了一半问题。它在模式匹配中起作用的原因是,有一个对象 :: 的提取器,它是在定义案例类时自动生成的。方便的是, ::.unapply 返回一个 List,因为 :: 扩展了 List。但是,如果您想对列表使用相同的技巧,您将无法扩展列表,因为它是最终的。您可以做的是使用适当的 unapp 方法定义一个对象,该方法具有预期的返回签名。例如,要匹配列表的最后一个元素,您可以执行以下操作:

object ::> {def unapply[A] (l: List[A]) = Some( (l.init, l.last) )}

List(1, 2, 3) match {
  case _ ::> last => println(last)
}

(1 to 9).toList match {
  case List(1, 2, 3, 4, 5, 6, 7, 8) ::> 9 => "woah!"
}
(1 to 9).toList match {
  case List(1, 2, 3, 4, 5, 6, 7) ::> 8 ::> 9 => "w00t!"
}

提取器必须返回一个选项,其中包含两个解构元素的元组。

Actually, the fact that :: is a case class is only half of the answer. The reason this works in pattern matching is that there is an extractor for object ::, which is generated automatically when a case class is defined. Conveniently, ::.unapply returns a List, because :: extends List. If you want to use the same trick for Lists, though, you won't be able to extend List, because it's final. What you can do is define an object with the appropriate unapply method, which has the expected return signature. For instance, to match the last element of a list, you can do:

object ::> {def unapply[A] (l: List[A]) = Some( (l.init, l.last) )}

List(1, 2, 3) match {
  case _ ::> last => println(last)
}

(1 to 9).toList match {
  case List(1, 2, 3, 4, 5, 6, 7, 8) ::> 9 => "woah!"
}
(1 to 9).toList match {
  case List(1, 2, 3, 4, 5, 6, 7) ::> 8 ::> 9 => "w00t!"
}

The extractor must return an Option, which contains a tuple of the two deconstructed elements.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文