I'm working through the scala labs stuff and I'm building out a function that will, in the end, return something like this:
tails(List(1,2,3,4)) = List(List(1,2,3,4), List(2,3,4), List(3,4), List(4), List())
I got this working by using two functions and using some recursion on the second one.
def tails[T](l: List[T]): List[List[T]] = {
if ( l.length > 1 )trailUtil(List() ::: List(l))
else List() ::: List(l);
}
def trailUtil[T](l:List[List[T]]) : List[List[T]] = {
if ( l.last.length == 0)l
else trailUtil(l :+ l.last.init);
}
This is all good a great but it's bugging me that I need two functions to do this. I tried switching: trailUtil(List() ::: List(l)) for an anonymous function but I got this error type mismatch; found :List[List[T]] required:Int from the IDE.
val ret : List[List[T]] = (ll:List[List[T]]) => {
if ( ll.last.length == 0) ll else ret(ll :+ ll.last.init)
}
ret(List() ::: List(1))
Could someone please point me to what I am doing wrong, or a better way of doing this that would be great.
(I did look at this SO post but the different type are just not working for me):
What about this:
def tails[T](l: List[T]): List[List[T]] =
l match {
case h :: tail => l :: tails(tail)
case Nil => List(Nil)
}
And a little bit less idiomatic version:
def tails[T](input: List[T]): List[List[T]] =
if(input.isEmpty)
List(List())
else
input :: tails(input.tail)
BTW try to avoid List.length, it runs in O(n) time.
UPDATE: as suggested by tenshi, tail-recursive solution:
#tailrec def tails[T](l: List[T], init: List[List[T]] = Nil): List[List[T]] =
l match {
case h :: tail => tails(tail, l :: init)
case Nil => init
}
You actually can define def inside another def. It allows to define function that actually has name which can be referenced and used for recursion. Here is how tails can be implemented:
def tails[T](l: List[T]) = {
#annotation.tailrec
def ret(ll: List[List[T]]): List[List[T]] =
if (ll.last.isEmpty) ll
else ret(ll :+ ll.last.tail)
ret(l :: Nil)
}
This implementation is also tail-recursive. I added #annotation.tailrec annotation in order to ensure that it really is (code will not compile if it's not).
You can also use build-in function tails (see ScalaDoc):
List(1,2,3,4).tails.toList
tails returns Iterator, so you need to convert it to list (like I did), if you want it. Also result will contain one extra empty in the end (in my example result would be List(List(1, 2, 3, 4), List(2, 3, 4), List(3, 4), List(4), List())), so you need deal with it.
What you are doing wrong is this:
val ret : List[List[T]]
So ret is a list of list of T. Then you do this:
ret(ll :+ ll.last.init)
That mean you are calling the method apply on a list of list of T. The apply method for lists take an Int parameter, and returns an element with that index. For example:
scala> List("first", "second", "third")(2)
res0: java.lang.String = third
I assume you wanted to write val ret: List[List[T]] => List[List[T]], that is, a function that takes a List[List[T]] and returns a List[List[T]]. You'd have other problems then, because val is referring to itself in its definition. To get around that, you could replace it with a lazy val:
def tails[T](l: List[T]): List[List[T]] = {
lazy val ret : List[List[T]] => List[List[T]] = { (ll:List[List[T]]) =>
if ( ll.last.length == 0) ll
else ret(ll :+ ll.last.init)
}
if ( l.length > 1 )ret(List() ::: List(l))
else List() ::: List(l);
}
But, of course, the easy solution is to put one def inside the other, like tenshi suggested.
You can also use folding:
val l = List(1,2,3,4)
l.foldLeft(List[List[Int]](l))( (outerList,element) => {
println(outerList)
outerList.head.tail :: outerList
})
The first parameter list is your start value/accumulator. The second function is the modifier. Typically, it modifies the start value, which is then passed to every element in the list. I included a println so you can see the accumulator as the list is iterated over.
Related
Suppose we have Seq val ourSeq = Seq(10,5,3,5,4).
I want to return a new list which reads from the left and stop when it sees a duplicate number (e.g. Seq(10,5,3) since 5 is repeated).
I was thinking of using fold left as such
ourSeq.foldLeft(Seq())(op = (temp, curr) => {
if (!temp.contains(curr)) {
temp :+ curr
} else break
})
but as far as I understand, there is no way to break out of a foldLeft?
Although it can be accomplished with a foldLeft() without any breaking out, I would argue that fold is the wrong tool for the job.
I'm rather fond of unfold(), which was introduced in Scala 2.13.0.
val ourSeq = Seq(10,5,3,5,4)
Seq.unfold((Set.empty[Int],ourSeq)){ case (seen,ns) =>
Option.when(ns.nonEmpty && !seen(ns.head)) {
(ns.head, (seen+ns.head, ns.tail))
}
}
//res0: Seq[Int] = Seq(10, 5, 3)
You are correct that it's not possible to break out of foldLeft. It would theoretically be possible to get the correct result with foldLeft, but you're still going to iterate the whole data structure. It'll be better to use an algorithm that already understands how to terminate early, and since you want to take a prefix, takeWhile will suffice.
import scala.collection.mutable.Set
val ourSeq = Seq(10, 5, 3, 5, 4)
val seen: Set[Int] = Set()
val untilDups = ourSeq.takeWhile((x) => {
if (seen contains x) {
false
} else {
seen += x
true
}
})
print(untilDups)
If you wanted to be totally immutable about this, you could wrap the whole thing in some kind of lazy fold that uses an immutable Set to keep its data. And that's certainly how I'd do it in Haskell. But this is Scala; we have mutability, and we may as well use it locally when it suits us.
This can be done using a recursive function:
def uniquePrefix[T](ourSeq: Seq[T]): List[T] = {
#annotation.tailrec
def loop(rem: List[T], res: List[T]): List[T] =
rem match {
case hd::tail if !res.contains(hd) =>
loop(tail, res :+ hd)
case _ =>
res
}
loop(ourSeq.toList, Nil)
}
This appears more complicated, but once you are familiar with the general pattern recursive functions are simple to write and more powerful than fold operations.
If you are working on large collections, this version is more efficient because it is O(n):
def distinctPrefix[T](ourSeq: Seq[T]): List[T] = {
#annotation.tailrec
def loop(rem: List[T], found: Set[T], res: List[T]): List[T] =
rem match {
case hd::tail if !found.contains(hd) =>
loop(tail, found + hd, hd +: res)
case _ =>
res.reverse
}
loop(ourSeq.toList, Set.empty, Nil)
}
This version works with any Seq and there are other options using Iterator etc. as described in the comments. You would need to be more specific about the type of the collection in order to create an optimised algorithm.
def uniquePrefix[T](ourSeq: Seq[T]): List[T] = {
#annotation.tailrec
def loop(rem: Seq[T], res: List[T]): List[T] =
rem.take(1) match {
case Seq(hd) if !res.contains(hd) =>
loop(rem.drop(1), res :+ hd)
case _ =>
res
}
loop(ourSeq, Nil)
}
Another option you have, is to use the function inits:
ourSeq.inits.dropWhile(curr => curr.distinct.size != curr.size).next()
Code run at Scastie.
I'm wondering what is idiomatic way to applying some operation on the List if it is not empty, and return empty List (Nil) if list is empty.
val result= myList match {
case Nil => Nil // this one looks bad for me
case nonEmpty => myService.getByFilters(nonEmpty)
}
Just using map operation on the list will trigger loop, but I want to achieve same result as map for Option type - i.e. do something only once if List is non-empty, and do nothing if List is empty
I think your design is not quite right perhaps. You should be just able to pass any list into the getByFilters function and it should just handle lists of any length. So there should be no need for these sorts of checks.
If the design change is not possible there is nothing wrong with if:
val result = if(myList.isEmpty) Nil else myService.getByFilters(myList)
It's idiomatic because if returns values. Maybe there are other clean ways, I don't know.
If you just want to require non empty list argument you can use HList or alternatively, you can use this trick:
def takesNonEmptyList[T](head: T, tail: T *): List[T] = head :: tail.toList
You can do something fake to make it seem look idiomatic, but I would not recommend it. It's unclear and unnecessary complication:
def getByFilters(xs: List[Int]) = xs.filter(_ % 2 == 0)
val res = l.headOption.map(_ :: l.tail).map(getByFilters).getOrElse(Nil)
println(res)
prints List(2, 4)
If you really want it, you can just implement your own semantic:
implicit class MySpecialList[T](xs: List[T]) {
def mapIfNotEmpty[R](f: List[T] ⇒ List[R]): List[R] =
if (xs.isEmpty) Nil else f(xs)
}
def getStuff(xs: List[Int]) = xs.map(_ + " OK")
val x: List[Int] = List(1,2,3)
val y: List[Int] = List()
def main(args: Array[String]): Unit = {
val xx = x.mapIfNotEmpty(getStuff) // List("1 OK", "2 OK", "3 OK")
val yy = y.mapIfNotEmpty(getStuff) // List()
}
There is method headOption in List, so you could use option semantic to lift List to Option[List]:
import scala.collection.TraversableLike
implicit class TraversableOption[T <: TraversableLike[_, T]](traversable: T) {
def opt: Option[T] = traversable.headOption.map(_ => traversable)
}
you can use it as:
val result = myList.opt.fold[List[Int]](Nil)(myService.getByFilters)
By invoking each filter service separately,
myList.flatMap(filter => myService.getByFilters(List(filter)))
it gets an empty list if myList is empty. If performance may be a matter, consider also a parallel version with
myList.par
In a project of mine one common use case keeps coming up. At some point I've got a sorted collection of some kind (List, Seq, etc... doesn't matter) and one element of this collection. What I want to do is to swap the given element with it's following element (if this element exists) or at some times with the preceding element.
I'm well aware of the ways to achieve this using procedural programming techniques. My question is what would be a good way to solve the problem by means of functional programming (in Scala)?
Thank you all for your answers. I accepted the one I myself did understand the most. As I'm not a functional programmer (yet) it's kind of hard for me to decide which answer was truly the best. They are all pretty good in my opinion.
The following is the functional version of swap with the next element in a list, you just construct a new list with elements swapped.
def swapWithNext[T](l: List[T], e : T) : List[T] = l match {
case Nil => Nil
case `e`::next::tl => next::e::tl
case hd::tl => hd::swapWithNext(tl, e)
}
A zipper is a pure functional data structure with a pointer into that structure. Put another way, it's an element with a context in some structure.
For example, the Scalaz library provides a Zipper class which models a list with a particular element of the list in focus.
You can get a zipper for a list, focused on the first element.
import scalaz._
import Scalaz._
val z: Option[Zipper[Int]] = List(1,2,3,4).toZipper
You can move the focus of the zipper using methods on Zipper, for example, you can move to the next offset from the current focus.
val z2: Option[Zipper[Int]] = z >>= (_.next)
This is like List.tail except that it remembers where it has been.
Then, once you have your chosen element in focus, you can modify the elements around the focus.
val swappedWithNext: Option[Zipper[Int]] =
for (x <- z2;
y <- x.delete)
yield y.insertLeft(x.focus)
Note: this is with the latest Scalaz trunk head, in which a bug with Zipper's tail-recursive find and move methods has been fixed.
The method you want is then just:
def swapWithNext[T](l: List[T], p: T => Boolean) : List[T] = (for {
z <- l.toZipper
y <- z.findZ(p)
x <- y.delete
} yield x.insertLeft(y.focus).toStream.toList) getOrElse l
This matches an element based on a predicate p. But you can go further and consider all nearby elements as well. For instance, to implement an insertion sort.
A generic version of Landei's:
import scala.collection.generic.CanBuildFrom
import scala.collection.SeqLike
def swapWithNext[A,CC](cc: CC, e: A)(implicit w1: CC => SeqLike[A,CC],
w2: CanBuildFrom[CC,A,CC]): CC = {
val seq: SeqLike[A,CC] = cc
val (h,t) = seq.span(_ != e)
val (m,l) = (t.head,t.tail)
if(l.isEmpty) cc
else (h :+ l.head :+ m) ++ l.tail
}
some usages:
scala> swapWithNext(List(1,2,3,4),3)
res0: List[Int] = List(1, 2, 4, 3)
scala> swapWithNext("abcdef",'d')
res2: java.lang.String = abcedf
scala> swapWithNext(Array(1,2,3,4,5),2)
res3: Array[Int] = Array(1, 3, 2, 4, 5)
scala> swapWithNext(Seq(1,2,3,4),3)
res4: Seq[Int] = List(1, 2, 4, 3)
scala>
An alternative implementation for venechka's method:
def swapWithNext[T](l: List[T], e: T): List[T] = {
val (h,t) = l.span(_ != e)
h ::: t.tail.head :: e :: t.tail.tail
}
Note that this fails with an error if e is the last element.
If you know both elements, and every element occurs only once, it gets more elegant:
def swap[T](l: List[T], a:T, b:T) : List[T] = l.map(_ match {
case `a` => b
case `b` => a
case e => e }
)
How about :
val identifierPosition = 3;
val l = "this is a identifierhere here";
val sl = l.split(" ").toList;
val elementAtPos = sl(identifierPosition)
val swapped = elementAtPos :: dropIndex(sl , identifierPosition)
println(swapped)
def dropIndex[T](xs: List[T], n: Int) : List[T] = {
val (l1, l2) = xs splitAt n
l1 ::: (l2 drop 1)
}
kudos to http://www.scala-lang.org/old/node/5286 for dropIndex function
I want to transform a List[Option[T]] into a Option[List[T]]. The signature type of the function is
def lo2ol[T](lo: List[Option[T]]): Option[List[T]]
The expected behavior is to map a list that contains only Somes into a Some containing a list of the elements inside the elements Some's. On the other hand, if the input list has at least one None, the expected behavior is to just return None. For example:
scala> lo2ol(Some(1) :: Some(2) :: Nil)
res10: Option[List[Int]] = Some(List(1, 2))
scala> lo2ol(Some(1) :: None :: Some(2) :: Nil)
res11: Option[List[Int]] = None
scala> lo2ol(Nil : List[Option[Int]])
res12: Option[List[Int]] = Some(List())
An example implementation, without scalaz, would be:
def lo2ol[T](lo: List[Option[T]]): Option[List[T]] = {
lo.foldRight[Option[List[T]]](Some(Nil)){(o, ol) => (o, ol) match {
case (Some(x), Some(xs)) => Some(x :: xs);
case _ => None : Option[List[T]];
}}}
I remember seeing somewhere a similar example, but using Scalaz to simplify the code. How would it look like?
A slightly more succinct version, using Scala2.8 PartialFunction.condOpt, but still without Scalaz:
import PartialFunction._
def lo2ol[T](lo: List[Option[T]]): Option[List[T]] = {
lo.foldRight[Option[List[T]]](Some(Nil)){(o, ol) => condOpt(o, ol) {
case (Some(x), Some(xs)) => x :: xs
}
}}
There's a function that turns a List[Option[A]] into an Option[List[A]] in Scalaz. It's sequence. To get None in case any of the elements are None and a Some[List[A]] in case all the elements are Some, you can just do this:
import scalaz.syntax.traverse._
import scalaz.std.list._
import scalaz.std.option._
lo.sequence
This method actually turns F[G[A] into G[F[A]] given that there exists an implementation of Traverse[F], and of Applicative[G] (Option and List happen to satisfy both and are provided by those imports).
The semantics of Applicative[Option] are such that if any of the elements of a List of Options are None, then the sequence will be None as well. If you want to get a list of all the Some values regardless of whether any other values are None, you can do this:
lo flatMap (_.toList)
You can generalize that for any Monad that also forms a Monoid (List happens to be one of these):
import scalaz.syntax.monad._
def somes[F[_],A](x: F[Option[A]])
(implicit m: Monad[F], z: Monoid[F[A]]) =
x flatMap (o => o.fold(_.pure[F])(z.zero))
For some reason you dislike
if (lo.exists(_ isEmpty)) None else Some(lo.map(_.get))
? That's probably the shortest in Scala without Scalaz.
Starting Scala 2.13, and the addition of the Option::unless builder to the standard library, a variant to Rex Kerr's answer would be:
Option.unless(list contains None)(list.flatten)
// val list = List(Some(1), Some(2)) => Some(List(1, 2))
// val list = List(Some(1), None, Some(2)) => None
or, if performance is at stake (in order to avoid flatten's implicit conversion from Option to List):
Option.unless(list contains None)(list.map(_.get))
While the Applicative[Option] in Scalaz has the wrong behaviour to directly use MA#sequence, you can also derive an Applicative from a Monoid. This is made convenient with MA#foldMapDefault or MA#collapse.
In this case, we use a Monoid[Option[List[Int]]. We first perform an inner map (MA#∘∘) to wrap the individual Ints in Lists of one element.
(List(some(1), none[Int], some(2)) ∘∘ {(i: Int) => List(i)}).collapse assert_≟ some(List(1, 2))
(List(none[Int]) ∘∘ {(i: Int) => List(i)}).collapse assert_≟ none[List[Int]]
(List[Option[Int]]() ∘∘ {(i: Int) => List(i)}).collapse assert_≟ none[List[Int]]
Abstracting from List to any container with instances for Traverse, Pointed and Monoid:
def co2oc[C[_], A](cs: C[Option[A]])
(implicit ct: Traverse[C], cp: Pointed[C], cam: Monoid[C[A]]): Option[C[A]] =
(cs ∘∘ {(_: A).pure[C]}).collapse
co2oc(List(some(1), none[Int], some(2))) assert_≟ some(List(1, 2))
co2oc(Stream(some(1), none[Int], some(2))) assert_≟ some(Stream(1, 2))
co2oc(List(none[Int])) assert_≟ none[List[Int]]
co2oc(List[Option[Int]]()) assert_≟ none[List[Int]]
Sadly, trying to compile this code currently either triggers #2741 or sends the compiler into an infinite loop.
UPDATE
To avoid traversing the list twice, I should have used foldMapDefault:
(List(some(1), none[Int], some(2)) foldMapDefault (_ ∘ ((_: Int).pure[List])))
This answer was based on the original request that an empty list, or a list containing only Nones, should return a None. Incidentally, this would be best modeled by the type Option[scalaz.NonEmptyList] -- NonEmptyList guarantees at least one element.
If you just want the a List[Int], there are many easier ways, given in other answers. Two direct ways that haven't been mentioned:
list collect { case Some(x) => x }
list flatten
This worked for me. I hope this is a correct solution.
It returns None if one of the Options in the List is None, otherwise it returns Option of List[A]
def sequence[A](a: List[Option[A]]): Option[List[A]] = {
a.foldLeft(Option(List[A]())) {
(prev, cur) => {
for {
p <- prev if prev != None
x <- cur
} yield x :: p
}
}
}
I am trying to understand the Scala quicksort example from Wikipedia. How could the sample be disassembled step by step and what does all the syntactic sugar involved mean?
def qsort: List[Int] => List[Int] = {
case Nil => Nil
case pivot :: tail =>
val (smaller, rest) = tail.partition(_ < pivot)
qsort(smaller) ::: pivot :: qsort(rest)
}
As much as I can gather at this stage qsort is a function that takes no parameters and returns a new Function1[List[Int],List[Int]] that implements quicksort through usage of pattern matching, list manipulation and recursive calls. But I can't quite figure out where the pivot comes from, and how exactly the pattern matching syntax works in this case.
UPDATE:
Thanks everyone for the great explanations!
I just wanted to share another example of quicksort implementation which I have discovered in the Scala by Example by Martin Odersky. Although based around arrays instead of lists and less of a show-off in terms of varios Scala features I personally find it much less convoluted than its Wikipedia counterpart, and just so much more clear and to the point expression of the underlying algorithm:
def sort(xs: Array[Int]): Array[Int] = {
if (xs.length <= 1) xs
else {
val pivot = xs(xs.length / 2)
Array.concat(
sort(xs filter (pivot >)),
xs filter (pivot ==),
sort(xs filter (pivot <)))
}
}
def qsort: List[Int] => List[Int] = {
case Nil => Nil
case pivot :: tail =>
val (smaller, rest) = tail.partition(_ < pivot)
qsort(smaller) ::: pivot :: qsort(rest)
}
let's pick apart a few bits.
Naming
Operators (such as * or +) are valid candidates for method and class names in Scala (hence you can have a class called :: (or a method called :: for that matter - and indeed both exist). Scala appears to have operator-overloading but in fact it does not: it's merely that you can declare a method with the same name.
Pattern Matching
target match {
case p1 =>
case p2 =>
}
Where p1 and p2 are patterns. There are many valid patterns (you can match against Strings, types, particular instances etc). You can also match against something called an extractor. An extractor basically extracts arguments for you in the case of a match, so:
target match {
case MyExtractor(arg1, arg2, arg3) => //I can now use arg1, arg2 etc
}
In scala, if an extractor (of which a case class is an example) exists called X, then the pattern X(a, b) is equivalent to a X b. The case class :: has a constructor taking 2 arguments and putting this together we get that:
case x :: xs =>
case ::(x, xs) =>
Are equivalent. This match says "if my List is an instance of :: extract the value head into x and tail into xs". pattern-matching is also used in variable declaration. For example, if p is a pattern, this is valid:
val p = expression
This why we can declare variables like:
val x :: xs = List(1, 2, 3)
val (a, b) = xs.partition(_ % 2 == 0 ) //returns a Tuple2 which is a pattern (t1, t2)
Anonymous Functions
Secondly we have a function "literal". tail is an instance of List which has a method called partition which takes a predicate and returns two lists; one of those entries satisfying the predicate and one of those entries which did not.
val pred = (el: Int) => e < 2
Declares a function predicate which takes an Int and returns true iff the int value is less than 2. There is a shorthand for writing functions inline
tail.partition(_ < pivot) // _ is a placeholder for the parameter
tail.partition( (e: Int) => e < pivot )
These two expressions mean the same thing.
Lists
A List is a sealed abstract class with only two implementations, Nil (the empty list) and :: (also called cons), which is a non-empty list consisting of a head and a tail (which is also a list). You can now see that the pattern match is a match on whether the list is empty or not. a List can be created by cons-ing it to other lists:
val l = 1 :: 2 :: Nil
val m = List(1, 2, 3) ::: List(4, 5, 6)
The above lines are simply method calls (:: is a valid method name in scala). The only difference between these and normal method calls is that, if a method end in a colon : and is called with spaces, the order of target and parameter is reversed:
a :: b === b.::(a)
Function Types
val f: A => B
the previous line types the reference f as a function which takes an A and returns a B, so I could then do:
val a = new A
val b: B = f(a)
Hence you can see that def qsort: List[Int] => List[Int] declares a method called qsort which returns a function taking a List[Int] and returning a List[Int]. So I could obviously do:
val l = List(2, 4, 1)
val m = qsort.apply(l) //apply is to Function what run is to Runnable
val n = qsort(l) //syntactic sugar - you don't have to define apply explicitly!
Recursion
When a method call is tail recursive, Scala will optimize this into the iterator pattern. There was a msitake in my original answer because the qsort above is not tail-recursive (the tail-call is the cons operator)
def qsort: List[Int] => List[Int] = {
case Nil => Nil
case pivot :: tail =>
val (smaller, rest) = tail.partition(_ < pivot)
qsort(smaller) ::: pivot :: qsort(rest)
}
Let's rewrite that. First, replace the function literal with an instance of Function1:
def qsort: List[Int] => List[Int] = new Function1[List[Int], List[Int]] {
def apply(input: List[Int]): List[Int] = input match {
case Nil => Nil
case pivot :: tail =>
val (smaller, rest) = tail.partition(_ < pivot)
qsort(smaller) ::: pivot :: qsort(rest)
}
}
Next, I'm going to replace the pattern match with equivalent if/else statements. Note that they are equivalent, not the same. The bytecode for pattern matches are more optimized. For instance, the second if and the exception throwing below do not exist, because the compile knows the second match will always happen if the first fails.
def qsort: List[Int] => List[Int] = new Function1[List[Int], List[Int]] {
def apply(input: List[Int]): List[Int] = if (input == Nil) {
Nil
} else if (input.isInstanceOf[::[_]] &&
scala.collection.immutable.::.unapply(input.asInstanceOf[::[Int]]) != None) {
val unapplyResult = scala.collection.immutable.::.unapply(input.asInstanceOf[::[Int]]).get
val pivot = unapplyResult._1
val tail = unapplyResult._2
val (smaller, rest) = tail.partition(_ < pivot)
qsort(smaller) ::: pivot :: qsort(rest)
} else {
throw new scala.MatchError(input)
}
}
Actually, val (smaller, rest) is pattern match as well, so Let's decompose it as well:
def qsort: List[Int] => List[Int] = new Function1[List[Int], List[Int]] {
def apply(input: List[Int]): List[Int] = if (input == Nil) {
Nil
} else if (input.isInstanceOf[::[_]] &&
scala.collection.immutable.::.unapply(input.asInstanceOf[::[Int]]) != None) {
val unapplyResult0 = scala.collection.immutable.::.unapply(input.asInstanceOf[::[Int]]).get
val pivot = unapplyResult0._1
val tail = unapplyResult0._2
val tmp0 = tail.partition(_ < pivot)
if (Tuple2.unapply(tmp0) == None)
throw new scala.MatchError(tmp0)
val unapplyResult1 = Tuple2.unapply(tmp0).get
val smaller = unapplyResult1._1
val rest = unapplyResult1._2
qsort(smaller) ::: pivot :: qsort(rest)
} else {
throw new scala.MatchError(input)
}
}
Obviously, this is highly unoptmized. Even worse, there are some function calls being done more than once, which doesn't happen in the original. Unfortunately, to fix that would require some structural changes to the code.
There's still some syntactic sugar here. There is an anonymous function being passed to partition, and there is the syntactic sugar for calling functions. Rewriting those yields the following:
def qsort: List[Int] => List[Int] = new Function1[List[Int], List[Int]] {
def apply(input: List[Int]): List[Int] = if (input == Nil) {
Nil
} else if (input.isInstanceOf[::[_]] &&
scala.collection.immutable.::.unapply(input.asInstanceOf[::[Int]]) != None) {
val unapplyResult0 = scala.collection.immutable.::.unapply(input.asInstanceOf[::[Int]]).get
val pivot = unapplyResult0._1
val tail = unapplyResult0._2
val func0 = new Function1[Int, Boolean] {
def apply(input: Int): Boolean = input < pivot
}
val tmp0 = tail.partition(func0)
if (Tuple2.unapply(tmp0) == None)
throw new scala.MatchError(tmp0)
val unapplyResult1 = Tuple2.unapply(tmp0).get
val smaller = unapplyResult1._1
val rest = unapplyResult1._2
qsort.apply(smaller) ::: pivot :: qsort.apply(rest)
} else {
throw new scala.MatchError(input)
}
}
For once, the extensive explanations about each syntactic sugar and how it works are being done by others. :-) I hope this complements their answers. Just as a final note, the following two lines are equivalent:
qsort(smaller) ::: pivot :: qsort(rest)
qsort(rest).::(pivot).:::(qsort(smaller))
The pivot in this pattern matching example is the first element of the list:
scala> List(1,2,3) match {
| case x :: xs => println(x)
| case _ => println("empty")
| }
1
The pattern matching is based on extractors and the cons is not part of the language. It uses the infix syntax. You can also write
scala> List(1,2,3) match {
| case ::(x,xs) => println(x)
| case _ => println("empty")
| }
1
as well. So there is a type :: that looks like the cons operator. This type defines how it is extracted:
final case class ::[B](private var hd: B, private[scala] var tl: List[B]){ ... }
It's a case class so the extractor will be generated by the Scala compiler. Like in this example class A.
case class A(x : Int, y : Int)
A(1,2) match { case x A y => printf("%s %s", x, y)}
-> 1 2
Based on this machinary patterns matching is supported for Lists, Regexp and XML.