【问题标题】:Scala Pattern Matching EnigmaScala 模式匹配之谜
【发布时间】:2015-03-17 17:29:59
【问题描述】:

这是我对 Scala 中 99 个问题的第三个问题 (P03) 的尝试 (http://aperiodic.net/phil/scala/s-99/):

import scala.annotation._

// Find the nth element of a list.
// nth(2, List(1, 1, 2, 3, 5, 8)) = 2

object P03 {
  @tailrec def nth[A](n: Int, ls: List[A]): A = (n, ls) match {
    case (0, h :: t :: Nil) => h
    case (n, _ :: t)        => nth(n - 1, t)
    case _                  => println(n); throw new IllegalArgumentException
}

谜团在于这段代码打印-4并抛出IllegalArgumentException

解决办法当然是把第一个模式改成:

case (0, h :: _) => h

现在打印正确答案2

问题是为什么?两者之间的细微差别是什么:

case (0, h :: t :: Nil) => h

&

case (0, h :: _) => h

谢谢!

【问题讨论】:

  • 区别在于h :: t :: Nil只匹配一个有两个元素的列表(htNil是一个列表结束的标记)而h :: _匹配每一个非空列表,即至少有一个元素的列表。
  • 您能否将其添加为答案而不是评论。我想将其标记为答案并关闭它:)。谢谢。

标签: scala pattern-matching


【解决方案1】:

不同之处在于 h :: t :: Nil 仅匹配具有两个元素的列表(htNil 是列表结尾的标记(我不能 100% 确定它是准确的命名法) )) 虽然h :: _ 匹配每个非空列表,即至少包含一个元素的列表,但如果您检查:: 类,您会看到:

final case class ::[B](private var hd: B, private[scala] var tl: List[B]) extends List[B]

它有一个头和一个尾,其中第一个是列表的第一个元素,第二个是其余元素,匹配h :: t :: Nil 意味着获取列表的第一个元素,而不是尾部的第一个元素然后在那里应该是Nil,匹配h :: _意味着得到头部,然后你不在乎剩下什么,只要有头部。

【讨论】:

    猜你喜欢
    • 2016-05-17
    • 2021-12-17
    • 2014-09-30
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-10-31
    相关资源
    最近更新 更多