I recently fell over a scala pattern match, that looked more or less like this:
def func (li :List[Int]): List[Int] = li match {
case Nil => Nil
case start :+ tail => start
case List() => li
}
Now, what these three different cases return is not so much what I am in interesed about.
I wondering whether a pattern match like this would ever have any effect? Is there any case at all, where third case could ever reached?
My initial thought is no, since all lists with more than 0 elements will always match on the first case, and therefore the second case could never be reached
You can read the post: Scala: Nil vs List(). From the point of view of pattern matching, they are the same. The third case will never hit.
In Scala source code you can find that case object Nil extends List[Nothing], and that empty list is Nil.
The third case is redundant, because as far as I know, an empty list can only ever be Nil. List is sealed, so there won't be classes other than :: and the object Nil extending it.
However, a list with more than 0 elements will always match on the second case. A list with no elements would match the first case (and the third case, if the first were not present).
Related
Is there any reason that matching an empty list should be done using a case/match instead of if/else, other than style? For example:
val a: List
def compute: Int =
if (a.isEmpty) 0
else a.sum
versus
def compute: Int =
a match {
case Nil => 0
case _ => a.sum // This is bad. For sake of illustration only.
}
If you are just testing empty/not empty then there is little to choose from and if is perhaps more meaningful. match comes in to play when there are multiple options:
a match {
case Nil => 0
case hd::Nil => 1
case hd::tl => 2
}
It is also often the case that you can avoid or at least defer this test by using appropriate methods. For example, take(1) works on an empty list whereas head will fail. And headOption.map(...) can be used to safely process the first element, if present.
Tim already has a good answer, but I'd like put a slightly different angle on it.
For lists (or other collections), .head and .tail are unsafe and if makes it easy to accidentally use them in the wrong branch (or to forget to test at all), while case avoids need to call these functions.
If your function doesn't need to call them and doesn't need to check more complex conditions, you can as well go with if.
Given a list, what is the best way to return a value depending on the empty-ness of that list?
Using match?
xs match {
case Nil => a
case _ => b
}
Or an if statement?
if (xs.isEmpty) a else b
It seems that pattern matching triggered a lot of a boilerplate in this case. Is there an idiomatic solution for this case?
"Preference" is subjective, but the simple if has a few advantages:
there doesn't seem to be a need to use pattern matching in this case, since you're not really exploiting its functionality (no extraction for example).
the second approach tells you explicitly that you check whether the list is empty, and hence is immediately readable.
In summary: pattern matching in Scala is a powerful tool, and because of its power it adds complexity to your code, both in terms of machine- and human-readability. In other words: not everything is a nail ;).
The pattern match syntax is preferred when you need recursion or head :: tail. List in Scala is inspired by older ML languages(Cons(head, tail)) and you get a nice head :: tail pair to match:
someList match {
case head :: tail => // this will actually be someList.head and someList.tail
case Nil => // ..
}
I wouldn't say it's nicer, but an alternative is:
xs.headOption.fold(a)(_ => b)
In this case, it looks a little bit weird because you're ignoring the head element and returning b instead, but if you actually wanted to use it as return value, the following is quite elegant:
xs.headOption.getOrElse(a) //will return the head element or a if none
My favourite would be adding some scalaz:
import scalaz._
import Scalaz._
xs.headOption ? b | a // if defined 'b' else 'a'
I am mucking around with scala implementing some common algorithms. While attempting to recreate a bubble sort I ran into this issue
Here is an implementation of an the inner loop that bubbles the value to the top:
def pass(xs:List[Int]):List[Int] = xs match {
case Nil => Nil
case x::Nil => x::Nil
case l::r::xs if(l>r) => r::pass(l::xs)
case l::r::xs => l::pass(r::xs)
}
My issue is with case Nil => Nil. I understand that I need this is because I could apply Nil to this function. Is there a way to ensure that Nil can't be provided as an argument in a manner that would satisfy the compiler so I can eliminate this case?
List has two subtypes, Nil and ::, so :: represents a list that has at least one element.
def pass(xs: ::[Int]):List[Int] = xs match {
case x::Nil => x::Nil
case l::r::xs if(l>r) => r::pass(new ::(l,xs))
case l::r::xs => l::pass(new ::(r, xs))
}
In that case you can simply play with the case clauses order:
def pass(xs:List[Int]):List[Int] = xs match {
case l::r::xs if(l>r) => r::pass(l::xs)
case l::r::xs => l::pass(r::xs)
case xs => xs
}
The first two clauses will only match lists with one or more elements. The last clause will match elsewhere.
This would roughly correspond to a refinement of the original type, where you would write a type whose members were a subset of the initial type. You would then show that, for every input x to your function, that x was non Nil. As this requires a good amount of proof (you can implement this in Coq with dependent types using a subset type), the better thing to do in this situation might be to introduce a new type, which was a list having no Nil constructor, only a constructor for cons and a single element.
EDIT: As Scala allows you to use subtyping over the List type to enforce this, you can prove it in the type system decidably using that subtype. This is still a proof, in the sense that any type checking corresponds to a proof that the program does indeed inhabit some type, it's just something the compiler can prove completely.
In Scala I have a List with an optional Option. This arises for example when you use for comprehension on a List and your yield returns an Option. In my case I was processing a JSON object and using for comprehension on the list of fields (List[JField]).
What's the best way to open up the list and map List() to None and List(Some(a)) to Some(a)?
A first approach would be
def headOrNone[A](list:List[Option[A]]) =
list match {
case Nil => None
case a::Nil => a
}
Another approach
def headOrNone[A](list:List[Option[A]]) = list.headOption.getOrElse(None)
A third approach (a variation on the headOption implementation)
def headOrNone[A](list:List[Option[A]]) = if (list.isEmpty) None else list.head
I personally prefer the third approach. Is there a better name for this function than headOrNone and what is the idiomatic scala way to write it?
You're solving a problem that probably shouldn't have been created. Instead, you probably want
for (x <- list) yield f(x) // Yields Option
to be
list.flatMap(f)
and then you'll have either zero or one things in your list to begin with (which you can extract using headOption).
How about this:
def headOrNone[A](list: List[Option[A]]) = list.flatten.headOption
headOrNone(List(Some(4))) // Some(4)
headOrNone(List()) // None
Though the first choice has the advantage of giving you an error if you happen to have list with more than one item, which, according to your description, seems like an error condition.
But personally, I would re-evaluate the code that produces the List[Option[A]] and see if there's a way to just have it return the right thing in the first place!
I am studying some scala code and found this method which baffles me. In the match statement, what is the sublist# construct? what kind of value does it contains? when I printed it its no diff than tail, but if I replace it with tail, the function returns diff result. Can somebody explain what it is and point me to a right resource to understand it? (I know I can search in google, but don't know what to look for..)
def flatMapSublists[A, B](ls: List[A])(f: (List[A]) => List[B]): List[B] =
ls match {
case Nil => Nil
case sublist#(_ :: tail) => f(sublist) ::: flatMapSublists(tail)(f)
}
I would call it the "eat your cake and have it too operator". At any level in pattern matching, you can give a part a name (before the #) and deconstruct it further (after the #). For instance imagine you want to match against a List with 3 elements, you need the second element, but you want to log the whole list:
something match {
case list#List(_,elem,_) => log("matching:" + list); elem
case _ => error("not found")
}
Without this feature, you had to write something like
something match {
case List(a,elem,b) => log("matching:" + List(a,elem,b)); elem
case _ => error("not found")
}
As you can see, we need to name the first and third element, just because we need them to get a list with the same structure on the right side, which is boilerplate. It is much easier and clearer if you can give the whole thing a name (list), and parts deeper in the structure as well (elem), when you need both on the right side.
In this instance, sublist becomes a named variable for the entire list (_ :: tail). tail is the, well, tail of the list. I'm not sure if there is a proper name for '#' here.
I don't really see the purpose of sublist here, since you can just reference ls directly.
Disclaimer: I'm new to scala. I hope I got this right.