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.
Related
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).
A/a case, not case case.
Apparently case a matches anything and binds it to the name a, while case A looks for an A variable and matches anything == considers equal to A. This came as quite a surprise to me; while I know Scala is case sensitive, I never expected identifier case to affect the parsing rules.
Is it common for Scala's syntax to care about the case of identifiers, or is there only a small number of contexts in which this happens? If there's only a small number of such contexts, what are they? I couldn't find anything on Google; all I got were results about pattern matching.
There is one more that is similar in nature, called a type pattern. In a type pattern, a simple identifier that starts with a lower case letter is a type variable, and all others are attempt to match actual types (except _).
For example:
val a: Any = List(1, 2, 3)
val c = 1
// z is a type variable
a match { case b: List[z] => a }
// Type match on `Int`
a match { case b: List[Int] => a }
// type match on the singleton c.type (not a simple lower case identifier)
// (doesn't actually compile because c.type will never conform)
a match { case b: List[c.type] => a }
Type matching like the the first example is lesser-known because, well, it's hardly used.
I have lots of pattern matching code that looks as follows: If some Foo matches, a Some of Bar is returned, otherwise None, and there are lots of Foos and long constructors for Bars. Something like:
y match {
case Foo1(z) => Some(Bar1(z))
case Foo2(z) => Some(Bar2(z))
case Foo3(z) => Some(Bar3(z))
case Foo4(z) => Some(Bar4(z))
case _ => None
}
In the actual code, the constructors on the right hand side of the arrows are more complex, and there are more cases.
Now, in order to get rid of the repetitive option constructors (Some), I could do:
Try(
y match {
case Foo1(z) => Bar1(z)
case Foo2(z) => Bar2(z)
case Foo3(z) => Bar3(z)
case Foo4(z) => Bar4(z)
}
).toOption
This looks significantly cleaner to me, and from a semantic perspective it is justifiable, as the case _ is actually a situation that should not occur, thus modeling it as an exception seems justifiable. Note that it is the repetitive Somes that bug me, not the last case.
My question is whether there is some (e.g. performance) penalty to the latter approach I am not aware of.
The second version is less readable, and less correct*. There isn't much of a point in using Try if you're just going to discard the error to None. The Try is only there to catch match errors and convert them to None, but you can do that in one like with case _ => None.
There would be slightly more overhead wrapping in Try, but not enough to matter. Correctness and readability should come first.
If you really don't want to have that extra case, consider wrapping y in Option and using collect:
Option(y) collect {
case Foo1(z) => Bar1(z)
case Foo2(z) => Bar2(z)
case Foo3(z) => Bar3(z)
case Foo4(z) => Bar4(z)
}
Using collect on an Option will wrap the cases in the partial function that are defined in Some, and any cases that do not match will become None.
*By correct, I mean widely accepted use of Try.
I found a strange working construct in scala:
(ArrayBuffer[Int]():Seq[Int]) match {
case Nil => "whoo"
case _ => "nayyy"
}
which returns
"whoo"
Apparently this already works partially for Vectors, but not pattern matching. can someone explain me that? Nil does not have any method named unapply. How is this possible?
With objects, unapply is not involved (that would be the case if you had used the hypothetical case Nil() => ...). Instead, the equality is checked using the equals method.
Equality for collections is defined in terms of their elements. E.g.
List(1,2,3) == Vector(1,2,3) // true!
The same happens with Nil which equals any empty sequence:
Vector() == Nil // true
collection.mutable.ArrayBuffer() == Nil // true
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'