【问题标题】:scala case classes questionsscala案例类问题
【发布时间】:2011-01-24 22:01:06
【问题描述】:

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

:: 可以用作

case head :: tail => ...

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

case foo op bar => ....

?

【问题讨论】:

  • 我的问题不仅仅是变量之间的'::'是怎么来的,还有一个案例类如何匹配另一个类的实例(原因是 List#:: 创建 ::案例类)
  • eed3si9n 引用的文字在第 3 页。 331 在“Scala 编程”(第 1 版)的 PDF 版中

标签: class scala case


【解决方案1】:
     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

【讨论】:

  • 很好的答案!所以诀窍是 List#:: 返回案例类 ::. 的一个实例
【解决方案2】:

Programming in Scala的第301页,关于Lists上的模式匹配中有详细说明。

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

【讨论】:

    【解决方案3】:

    实际上, :: 是一个案例类这一事实只是答案的一半。这在模式匹配中起作用的原因是对象 :: 有一个 extractor,它是在定义案例类时自动生成的。方便的是, ::.unapply 返回一个列表,因为 :: 扩展了列表。但是,如果您想对 List 使用相同的技巧,您将无法扩展 List,因为它是 final。您可以做的是使用适当的 unapply 方法定义一个对象,该方法具有预期的返回签名。例如,要匹配列表的 last 元素,您可以这样做:

    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!"
    }
    

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

    【讨论】:

    • 我不认为 unapply 在这里适用 scala> val l = List(1, 2 , 3) l: List[Int] = List(1, 2, 3) scala> scala.:: .unapply(l) :6: 错误:类型不匹配;发现 : List[Int] required: ::[?] val r = scala.::(1, Nil) r: ::[Int] = List(1) scala> scala.::.unapply(r) res7: Some[List[Int]] = Some(List()) 所以 unapply 仅在实际由案例类构造时才有效,不适用于一般列表。
    • 案例类创建的 unapply 没有什么特别之处。请注意, List 是抽象的,实际上任何非空列表都是 scala.:: List(1).isInstanceOf[::[Int]] 的实例,这意味着您在模式中匹配的实际上是 scala.: : (除非它是零)。还要注意,只要您只重新定义 unapply for ::,Lists 的模式匹配就会中断: object :: {def unapply = false}
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多