从Scala中的Book编程我得到以下代码:
val second: List[ Int] => Int = { case x :: y :: _ => y }
//warning: match may not be exhaustive.
它声明如果列表不为空或为零,则此函数将返回整数列表的第二个元素。 Stil这部分对我来说有点尴尬:
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
答案 0 :(得分:1)
值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
答案 1 :(得分:1)
在REPL中,您可以输入:
scala> val list = "a" :: "b" :: Nil
list: List[String] = List(a, b)
从右到左阅读,意味着以List(Nil)结束,在字符串“b”之前和此List(“b”:: Nil)前面添加字符串a,a ::( “b”:: Nil)但你不需要parens,所以它可以写成“a”::“b”:: Nil。
在模式匹配中,您会经常看到:
... list match {
case Nil => // ...
case x :: xs => // ...
}
区分空列表和非空,其中xs可能是列表的其余部分,但也匹配Nil,如果整个列表是(“b”:: Nil),例如,则x =“b”和xs =无。
但是如果list =“a”::“b”:: Nil,那么x =“a”和xs =(b :: Nil)。
在你的例子中,解构只是一步,而不是像xs这样的名字,使用了小丑符号_,表示该名称可能没有被使用而且没有发挥作用。
答案 2 :(得分:1)
首先。当您考虑模式匹配时,您应该考虑匹配结构。
case
语句的第一部分描述了一个结构。该结构可以描述对于导出结果有用的一个或多个事物(变量)。
在您的示例中,您有兴趣派生列表的第二个元素。在Scala中构建列表的简写是使用::
方法(也称为 cons )。 ::
也可用于描述case
语句中的结构。 目前,您不应该考虑在::
的第一部分评估case
方法。可能是你说_.::(y).::(x)
评价的原因。 ::
cons运算符帮助我们根据元素描述列表的结构。在这种情况下,第一个元素(x
),第二个元素(y
)和其余元素(_
通配符)。我们感兴趣的是一个结构,它是一个至少有2个元素的列表,第三个可以是任何东西 - 一个Nil表示列表的结尾或另一个元素 - 因此是通配符。
case语句的第二部分,使用第二个元素派生结果(y
)。
更多关于列表和消费
Scala中的列表类似于LinkedList
。您知道名为head
的第一个元素以及列表其余部分的开头。遍历链接列表时,如果列表的其余部分为Nil
,则停止。这个::
cons运算符可以帮助我们可视化链表的结构。虽然Scala编译实际上会调用::
方法,正如您所描述的那样从右到左进行评估_.::(y).::(x)
顺便说一句,你可能已经注意到Scala编译器可能会抱怨你的匹配并不详尽。这意味着此second
方法适用于任何大小的列表。因为没有任何case
语句来描述具有零个或一个元素的列表。此外,如前面答案的评论中所述,如果您对第一个元素不感兴趣,可以将其描述为通配符_
。
case _ :: y :: _ => y
我希望这有帮助。
答案 3 :(得分:0)
如果你在scala中看到列表的结构为<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css">
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/js/bootstrap.min.js"></script>
<body>
<div class="container">
<p id="paragraph">word is sold</p>
</div>
</body>
,则第一个元素被视为head,所有剩余的元素被视为tail(Nil将是tail的最后一个元素)。每当你执行x :: y :: _时,x将匹配列表的头部,剩下的将是尾部,y将匹配下一个列表的头部(第一个列表的尾部)
例如:
head::tail
您可以通过不同的方式查看此列表:
val l = List(1,2,3,4,5)
等等
所以尝试匹配模式。在你的问题中,y将给出第二个元素