Scala中case语句里cons运算符及占位符作用解析
Understanding Right-Associative Operators and Underscores in Scala Pattern Matching
Great question—let’s unpack both parts of your confusion clearly, using your findKth1 example as a reference.
1. Why the Cons Operator (::) Works in Case Statements (Pattern Matching)
First, let’s clarify: the :: operator (Scala’s list "cons" operator) isn’t just a regular operator—it’s deeply tied to Scala’s pattern matching mechanism via extractors. Here’s the breakdown:
- Scala’s
Listis built using::as its core constructor. When you write3 :: 4 :: 5 :: 6 :: Nil, you’re actually calling the right-associative method::on the tail list (since operators ending with:are right-associative in Scala). So3 :: List(4,5,6)is equivalent toList(4,5,6).::(3). - For pattern matching, Scala supports infix patterns (writing operators in the middle of a pattern). When you use
h :: _or_ :: tailin a case statement, this is shorthand for::(h, _)or::(_, tail). The::companion object implements anunapplymethod, which is what enables pattern matching: it takes a list and splits it into its head and tail (if the list is non-empty). - That’s why
case (0, h::_)works: it matches a tuple where the first element is 0, and the second is a non-empty list—extracting the head intohand ignoring the tail (via_).
2. The Role of Underscores (_) in This Code
In your findKth1 function, the underscores serve two related but distinct roles in pattern matching:
- Wildcard for unused values: When you see
h::_or_::tail, the_acts as a wildcard. It means "match any value here, but I don’t need to assign it to a variable because I won’t use it in the case body." For example:h::_matches any non-empty list, captures the head intoh, and discards the tail (since we don’t need it for the 0th element case)._::tailmatches any non-empty list, discards the head (we don’t care what it is—we just need the tail to recurse on), and captures the tail intotail.
- Catch-all pattern: The final
case _ =>uses_as a catch-all. It matches any input that didn’t fit the previous two cases (like a negativek, or an empty list whenkis still positive), triggering theNoSuchElementException.
Note: This is different from the underscore’s role in anonymous functions (e.g., List(1,2,3).map(_ * 2) where _ is a placeholder for the function parameter). In pattern matching, it’s purely a wildcard for values you don’t need to reference.
Your Code Example, Annotated
def findKth1[A](k:Int, l:List[A]):A = (k, l) match { case (0, h::_) => h // _ = ignore the tail; extract head h case(k, _::tail) if k > 0 => findKth1(k - 1, tail) // _ = ignore the head; extract tail case _ => throw new NoSuchElementException // _ = catch all other cases } findKth1(2, List(3,4,5,6)) // Returns 5, as expected
内容的提问来源于stack exchange,提问作者Jwan622
相关产品推荐
相关产品推荐

