我有以下代码,它对现在列表中的每个元素进行递归操作
def doMatch(list: List[Int]): Unit = list match {
case last :: Nil => println("Final element.")
case head :: tail => println("Recursing..."); doMatch(tail)
}
,忽略可以通过 filter() 和 foreach() 使用此功能,这工作得很好。但是,如果我尝试更改它以接受任何 Seq[Int],我会遇到问题:
- Seq 没有 ::,但它确实有 +:,据我所知,这基本上是同样的事情。但是,如果我尝试在 head +: tail 上匹配,编译器会抱怨“错误:未找到:值+:”
- Nil 特定于 List,并且我不确定用什么替换它。如果我解决了上一个问题,我将尝试 Seq()
这是我认为代码应该看起来的样子,除了它不起作用:
def doMatch(seq: Seq[Int]): Unit = seq match {
case last +: Seq() => println("Final element.")
case head +: tail => println("Recursing..."); doMatch(tail)
}
编辑:这么多好的答案!我接受agilesteel的答案,因为他是第一个指出 :: 在我的示例中不是运算符,而是案例类,因此存在差异的答案。
I have the following code which recursively operates on each element within a List
def doMatch(list: List[Int]): Unit = list match {
case last :: Nil => println("Final element.")
case head :: tail => println("Recursing..."); doMatch(tail)
}
Now, ignoring that this functionality is available through filter() and foreach(), this works just fine. However, if I try to change it to accept any Seq[Int], I run into problems:
- Seq doesn't have ::, but it does have +:, which as I understand is basically the same thing. If I try to match on head +: tail however, the compiler complains 'error: not found: value +:'
- Nil is specific to List, and I'm not sure what to replace it with. I'm going to try Seq() if I ever get past the previous problem
Here is how I think the code should look, except it doesn't work:
def doMatch(seq: Seq[Int]): Unit = seq match {
case last +: Seq() => println("Final element.")
case head +: tail => println("Recursing..."); doMatch(tail)
}
Edit: So many good answers! I'm accepting agilesteel's answer as his was the first that noted that :: isn't an operator in my example, but a case class and hence the difference.
发布评论
评论(6)
截至 2012 年 3 月的 IDE,这在 2.10+ 中有效:
更一般地,为 Seq 添加了两个不同的 head/tail 和 init/last 分解对象,镜像附加/前置href="https://github.com/scala/scala/commit/b3efb3d493605d1c7e106e5f0a697b52ebb3d97c">SeqExtractors:
As of the ides of March 2012, this works in 2.10+:
More generally, two different head/tail and init/last decomposition objects mirroring append/prepend were added for
Seq
in SeqExtractors:有点作弊,但事情是这样的:
不要问我为什么
xs*
不起作用......Kind of cheating, but here it goes:
Don't ask me why
xs*
doesn't work...Scala 中有两个
::
(发音为 cons)。一种是在class List
中定义的运算符,另一种是class(List
的子类),表示一个具有头和尾特征的非空列表。head :: tail
是一个构造函数模式,它在语法上是从::(head, tail)
修改而来的。::
是一个案例类,这意味着为其定义了一个提取器对象。There are two
::
(pronounced cons) in Scala. One is an operator defined inclass List
and one is a class (subclass ofList
), which represents a non empty list characterized by a head and a tail.head :: tail
is a constructor pattern, which is syntactically modified from::(head, tail)
.::
is a case class, which means there is an extractor object defined for it.您实际上可以为
+:
定义一个对象来完全执行您正在寻找的操作:然后您的代码将完全按照预期工作。
这是有效的,因为当用于模式匹配时,
h +: t
相当于+:(h,t)
。You can actually define an object for
+:
to do exactly what you are looking for:Then your code works exactly as expected.
This works because
h +: t
is equivalent to+:(h,t)
when used for patten matching.我认为标准库中不存在对任意序列的模式匹配支持。不过,您可以在没有模式匹配的情况下完成此操作:
不过,您可以定义自己的提取器对象。请参阅http://www.scala-lang.org/node/112
I don't think there is pattern matching support for arbitrary sequences in the standard library. You could do it with out pattern matching though:
You can define your own extractor objects though. See http://www.scala-lang.org/node/112
从 Seq 到 List 的简单转换就可以完成这项工作:
A simple tranformation from Seq to List would do the job: