使用模式匹配时,我可以使用::或:运算符,它们似乎可以互换
val s=Seq(1,2,3) s match{ case x :: l => ...
但是当我试图在不同的情况下使用::
val s=1::Seq(2,3)
我收到“value ::不是Seq [Int]”成员的消息.我明白我应该使用Seq的=和=运算符,但为什么呢
::仅在模式匹配场景中工作?
解决方法
scala> val s = Seq(1,3) s: Seq[Int] = List(1,3)
所以值s的类型是Seq [Int],但它指向的对象是List [Int]类型.那没关系,因为List扩展了Seq.那当然会匹配一个涉及::的模式,因为它实际上是一个List:
scala> s match { case x :: xs => x } res2: Int = 1
但是表达式Seq(1,3)的类型不是List [Int]而是Seq [Int] – 即使实际对象确实是List.因此,以下失败是因为Seq没有定义::方法:
scala> val s = 1 :: Seq(2,3) <console>:7: error: value :: is not a member of Seq[Int] val s = 1 :: Seq(2,3)
您必须使用Seq的方法:
scala> val s = 1 +: Seq(2,3)
您混淆的关键是当您对类似s的值调用方法时,可用的方法集完全取决于值的静态类型,而模式匹配则检查匹配的对象是否为class ::.
为了说明这一点,让我们编译一些示例代码并使用javap来查看字节码;第一个方法的前几个指令检查参数是否为class ::(而不是其他一些扩展Seq的类)并强制转换为它:
NS% cat Test.scala object Test { def first(xs: Seq[Int]) = xs match { case x :: xs => x } } NS% javap -c Test\$.class Compiled from "Test.scala" public final class Test${ public static final Test$MODULE$; public static {}; Code: 0: new #2 // class Test$ 3: invokespecial #12 // Method "<init>":()V 6: return public int first(scala.collection.Seq<java.lang.Object>); Code: 0: aload_1 1: astore_2 2: aload_2 3: instanceof #16 // class scala/collection/immutable/$colon$colon 6: ifeq 30 9: aload_2 10: checkcast #16 // class scala/collection/immutable/$colon$colon 13: astore_3 14: aload_3 15: invokevirtual #20 // Method scala/collection/immutable/$colon$colon.head:()Ljava/lang/Object; 18: invokestatic #26 // Method scala/runtime/BoxesRunTime.unBoxToInt:(Ljava/lang/Object;)I 21: istore 4 23: iload 4 25: istore 5 27: iload 5 29: ireturn 30: new #28 // class scala/MatchError 33: dup 34: aload_2 35: invokespecial #31 // Method scala/MatchError."<init>":(Ljava/lang/Object;)V 38: athrow
最后,您可以问为什么Scala人没有为Seq制作::等效方法(前置元素).如果有,那么1 :: Seq(2,3)就可以了.
但是对于Seq来说,他们确实需要一对运算符,一个是前置的(这个必须以冒号结尾,因此它是右关联的)和一个要追加的运算符.您希望避免将元素附加到List,因为您必须遍历现有元素才能执行此操作,但对于Seqs通常不会这样 – 例如追加对于Vector非常有效.所以他们选择:for prepend和:for append.
当然,你可以问为什么他们没有使用:for List匹配Seq.我不知道答案的完整答案.我知道::来自其他具有列表结构的语言,因此部分答案可能与已建立的约定一致.也许他们没有意识到他们想要一个匹配的运算符对于超类型的List,直到为时已晚 – 不确定.有谁知道这里的历史?
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。