Scala 列表的第二个元素
从《Scala编程》一书中,我得到了以下代码行:Scala 列表的第二个元素,scala,list,Scala,List,从《Scala编程》一书中,我得到了以下代码行: val second: List[ Int] => Int = { case x :: y :: _ => y } //warning: match may not be exhaustive. 它声明,如果整数列表不是空的或为零,则此函数将返回整数列表的第二个元素。这部分对我来说还是有点尴尬: case x :: y :: _ 这究竟是怎么回事?这是否对任何至少包含2个元素的列表进行数学运算,然后返回第二个元素?如果是的话,还
val second: List[ Int] => Int = { case x :: y :: _ => y }
//warning: match may not be exhaustive.
它声明,如果整数列表不是空的或为零,则此函数将返回整数列表的第二个元素。这部分对我来说还是有点尴尬:
case x :: y :: _
这究竟是怎么回事?这是否对任何至少包含2个元素的列表进行数学运算,然后返回第二个元素?如果是的话,还有人能解释一下语法吗?我知道::是在正确的操作数上调用的。所以它可以写成
(_.::(y)).::(X)
我还是不明白为什么会返回2
val second: List[ Int] => Int = { case x :: y :: _ => y }
var x = List(1,2)
second(x) //returns 2
值
second
是函数类型,它接受List[Int]
并返回Int
如果列表中有第一个元素(“x”)和第二个元素(“y”),那么无论接下来发生什么(我们不关心它),我们只返回元素“y”(这是列表中的第二个元素)
在任何其他情况下,都不会定义该函数。您可以检查:
scala> val second: PartialFunction[List[Int], Int] = {
| case x :: y :: _ => y
| }
second: PartialFunction[List[Int],Int] = <function1>
scala> second.isDefinedAt(List(1,2,3))
res18: Boolean = true
scala> second.isDefinedAt(List(1,2))
res19: Boolean = true
scala> second.isDefinedAt(List(0))
res20: Boolean = false
scala>val second:PartialFunction[List[Int],Int]={
|案例x::y::=>y
| }
第二:部分函数[List[Int],Int]=
scala>second.isDefinedAt(列表(1,2,3))
res18:布尔值=真
scala>second.isDefinedAt(列表(1,2))
res19:布尔值=真
scala>second.isDefinedAt(列表(0))
res20:布尔值=假
在REPL中,您可以键入:
scala> val list = "a" :: "b" :: Nil
list: List[String] = List(a, b)
它是从右到左读取的,意思是取一个列表的结尾(Nil),前置字符串“b”,然后到这个列表(“b”::Nil)前置字符串a,a:(“b”::Nil),但是你不需要paren,所以它可以写为“a”::“b”::Nil”
在模式匹配中,您将更经常看到:
... list match {
case Nil => // ...
case x :: xs => // ...
}
要区分空列表和非空列表,其中xs可能是列表的其余部分,但也匹配Nil,例如,如果整个列表是(“b”::Nil),则x=“b”和xs=Nil
但是如果list=“a”::“b”::Nil,那么x=“a”和xs=(b::Nil)
在您的示例中,解构只是多了一步,而不是像xs这样的名称,而是使用了小丑符号uu,表示该名称可能没有使用,也没有发挥作用。首先。当您考虑模式匹配时,您应该考虑匹配结构
case
语句的第一部分描述了一个结构。此结构可能描述一个或多个对推导结果有用的事物(变量)
在您的示例中,您感兴趣的是派生列表的第二个元素。在Scala中构建列表的简写方法是使用:
方法(也称为cons):
也可用于描述case
语句中的结构此时,您不应该在案例的第一部分中考虑对:
方法的评估。也许这就是为什么你要说。::(y)。:(x)
。::
cons操作符帮助我们描述列表的元素结构。在这种情况下,第一个元素(x
),第二个元素(y
)和它的其余部分(
通配符)。我们感兴趣的是一个结构,它是一个至少有2个元素的列表,第三个元素可以是任何东西-一个Nil表示列表的结尾或另一个元素-因此是通配符
case语句的第二部分使用第二个元素派生结果(y
)
更多关于列表和考虑的信息
Scala中的列表类似于链接列表
。您知道名为head
的第一个元素以及列表其余部分的开头。当遍历链接列表时,如果列表的其余部分为Nil
,则停止。这个::
cons操作符帮助我们可视化链表的结构。尽管Scala compile实际上会调用::
方法,如您所述从右到左求值。::(x)
顺便说一句,您可能已经注意到Scala编译器可能会抱怨您的匹配不够详尽。这意味着这个second
方法将适用于任何大小的列表。因为没有任何case
语句来描述包含零或一个元素的列表。此外,如前面答案的注释所述,如果您对第一个元素不感兴趣,可以将其描述为通配符。
case\uuu::y::\u=>y
我希望这有帮助 如果您在scala its的head::tail
中看到列表的结构,则第一个元素被视为head,其余所有元素都被视为tail(Nil将是tail的最后一个元素)。每当执行x::y::\时,x将匹配列表的开头,剩余的将是尾部,y将再次匹配下一个列表的开头(第一个列表的尾部)
例如:
您可以通过不同的方式查看此列表:
1::2::3::4::5::Nil
1::List(2,3,4,5)
1::2::List(2,3,4,5)
等等
因此,尝试匹配模式。在您的问题中,y将给出第二个元素x
可能是\u
@Jubobs,这是正确的。除了下面的答案之外,我建议您阅读以下内容:它涉及提取器/未应用,以及它们与模式匹配的关系。它有点过时,但仍然是正确的,真的很好的解释!感谢您花时间以如此简洁的方式写下这篇文章。谢谢@Hansherrich
1::2::3::4::5::Nil
1::List(2,3,4,5)
1::2::List(2,3,4,5)