scala – 为什么我可以在模式匹配中使用:: operator和Seq,但在其
所以我对
Scala中Seq的这种行为感到困惑.
使用模式匹配时,我可以使用::或:运算符,它们似乎可以互换 val s=Seq(1,2,3) s match{ case x :: l => ... 但是当我试图在不同的情况下使用:: val s=1::Seq(2,3) 我收到“value ::不是Seq [Int]”成员的消息.我明白我应该使用Seq的=和=运算符,但为什么呢 解决方法
::是列表,事实上Seq.apply目前会给你一个列表:
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,直到为时已晚 – 不确定.有谁知道这里的历史? (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |