match
operator continues to amaze me.Here's one I just found tonight. In all my
match
code so far, I've always had conditions for an empty list (case Nil =>
) and a list with at least one item, which I usually write as case item :: moreItems =>
Tonight I needed to have a different case for when there is ONLY one item in the list. I thought, "I wonder if I can put
Nil
on the right-hand side of the ::?" And, sure enough, as has almost always been the case when I've asked "can match
do this?", the answer was yes.Code:
object TestingObject {Output:
def main(args: Array[String]) {
isOneItemList(Nil)
isOneItemList(List())
isOneItemList(List("1"))
isOneItemList(List("1", "2"))
isOneItemList(List("1", "2", "3"))
isOneItemList(List("1", "2", "3", "4"))
}
def isOneItemList(list: List[String]) : Unit = {
println(list + " => " +
(list match {
case Nil => "Nope: it's empty"
case one :: Nil => "Yep: just one"
case one :: two :: Nil => "Nope: there's exactly two"
case _ => "Nope: there's at least three"
})
)
}
}
List() => Nope: it's empty
List() => Nope: it's empty
List(1) => Yep: just one
List(1, 2) => Nope: there's exactly two
List(1, 2, 3) => Nope: there's at least three
List(1, 2, 3, 4) => Nope: there's at least three
FYI, you don't have to use :: operator for matching lists. This also works:
ReplyDeletelist match {
case Nil => "Nope: it's empty"
case List(one) => "Yep: just one"
case List(one, two) => "Nope: there's exactly two"
case _ => "Nope: there's at least three"
}
In my opinion, this makes it more clear that you are actually looking for list of one or two elements.
Thanks for that, Margus!
ReplyDeleteI've had a lot more practice with using and writing extractors since this post, so lately I think I have been doing what you suggested.
It's funny sometimes to look back on how you did things when you were first learning.
Cheers,
Graham.