Scala debug this recursive example - scala

def append[T](xs: List[T], ys: List[T]): List[T] =
println(xs)
xs match {
case List() => ys
case x :: xs1 => x :: append(xs1, ys)
}
append(List(1,2), List(3,4));
So the println(xs) code won't run.I basically want to see what hapepns when xs1 is just a single element array. But how can I do this? I basically want to see if this is single element list is deconstructed into the single element and xs1 is like null or [] on the next pass.
What debuggers does Scala have? How can I use them? Why doesn't println(xs) work?

Related

Function takes two List[Int] arguments and produces a List[Int]. SCALA [duplicate]

This question already has answers here:
Scala - Combine two lists in an alternating fashion
(4 answers)
Closed 3 years ago.
The elements of the resulting list should alternate between the elements of the arguments. Assume that the two arguments have the same length.
USE RECURSION
My code as follows
val finalString = new ListBuffer[Int]
val buff2= new ListBuffer[Int]
def alternate(xs:List[Int], ys:List[Int]):List[Int] = {
while (xs.nonEmpty) {
finalString += xs.head + ys.head
alternate(xs.tail,ys.tail)
}
return finalString.toList
}
EXPECTED RESULT:
alternate ( List (1 , 3, 5) , List (2 , 4, 6)) = List (1 , 2, 3, 4, 6)
As far for the output, I don't get any output. The program is still running and cannot be executed.
Are there any Scala experts?
There are a few problems with the recursive solutions suggested so far (including yours, which would actually work, if you replace while with if): appending to end of list is a linear operation, making the whole thing quadratic (taking a .length of a list too, as well ас accessing elements by index), don't do that; also, if the lists are long, a recursion may require a lot of space on the stack, you should be using tail-recursion whenever possible.
Here is a solution that is free of both those problems: it builds the output backwards, by prepending elements to the list (constant time operation) rather than appending them, and reverses the result at the end. It is also tail-recursive: the recursive call is the last operation in the function, which allows the compiler to convert it into a loop, so that it will only use a single stack frame for execution regardless of the size of the lists.
#tailrec
def alternate(
a: List[Int],
b: List[Int],
result: List[Int] = Nil
): List[Int] = (a,b) match {
case (Nil, _) | (_, Nil) => result.reversed
case (ah :: at, bh :: bt) => alternate(at, bt, bh :: ah :: result)
}
(if the lists are of different lengths, the whole thing stops when the shortest one ends, and whatever is left in the longer one is thrown out. You may want to modify the first case (split it into two, perhaps) if you desire a different behavior).
BTW, your own solution is actually better than most suggested here: it is actually tail recursive (or rather can be made one if you add else after your if, which is now while), and appending to ListBuffer isn't actually as bad as to a List. But using mutable state is generally considered "code smell" in scala, and should be avoided (that's one of the main ideas behind using recursion instead of loops in the first place).
Condition xs.nonEmpty is true always so you have infinite while loop.
Maybe you meant if instead of while.
A more Scala-ish approach would be something like:
def alternate(xs: List[Int], ys: List[Int]): List[Int] = {
xs.zip(ys).flatMap{case (x, y) => List(x, y)}
}
alternate(List(1,3,5), List(2,4,6))
// List(1, 2, 3, 4, 5, 6)
A recursive solution using match
def alternate[T](a: List[T], b: List[T]): List[T] =
(a, b) match {
case (h1::t1, h2::t2) =>
h1 +: h2 +: alternate(t1, t2)
case _ =>
a ++ b
}
This could be more efficient at the cost of clarity.
Update
This is the more efficient solution:
def alternate[T](a: List[T], b: List[T]): List[T] = {
#annotation.tailrec
def loop(a: List[T], b: List[T], res: List[T]): List[T] =
(a, b) match {
case (h1 :: t1, h2 :: t2) =>
loop(t1, t2, h2 +: h1 +: res)
case _ =>
a ++ b ++ res.reverse
}
loop(a, b, Nil)
}
This retains the original function signature but uses an inner function that is an efficient, tail-recursive implementation of the algorithm.
You're accessing variables from outside the method, which is bad. I would suggest something like the following:
object Main extends App {
val l1 = List(1, 3, 5)
val l2 = List(2, 4, 6)
def alternate[A](l1: List[A], l2: List[A]): List[A] = {
if (l1.isEmpty || l2.isEmpty) List()
else List(l1.head,l2.head) ++ alternate(l1.tail, l2.tail)
}
println(alternate(l1, l2))
}
Still recursive but without accessing state from outside the method.
Assuming both lists are of the same length, you can use a ListBuffer to build up the alternating list. alternate is a pure function:
import scala.collection.mutable.ListBuffer
object Alternate extends App {
def alternate[T](xs: List[T], ys: List[T]): List[T] = {
val buffer = new ListBuffer[T]
for ((x, y) <- xs.zip(ys)) {
buffer += x
buffer += y
}
buffer.toList
}
alternate(List(1, 3, 5), List(2, 4, 6)).foreach(println)
}

What is the meaning of case in match pattern in scala?

val list1 = List(1, 1, 2, 3, 5,7,8,4)
def lastrecursive[A](ls :List[A]):A = ls match{
case p :: Nil => p // what is the meaning of Nil
case _ :: tail => lastrecursive(tail)
case _ => throw new NoSuchElementException
}
For the code ABOVE in recursive format. Can anyone explain why we are giving
:: and case h and case tail and case _. while working on list match pattern.
and for reversing a list
def reverseRecursive[A](ls: List[A]): List[A] = ls match {
case Nil => Nil
case h :: tail => reverseRecursive(tail) ::: List(h)
}
how this ::: List(h) works?
the :: method is used to construct and deconstruct a list. a::b means the head of the list is a (a single element) and the tail is b (a list).
p::Nil means a case where there is some element p and the tail is the empty list (Nil).
This case basically finds the last actual element in the list.
The second case is similar: h::tail means an element h and a list tail. So we reverse the tail and then add the list of h to the end (l1 ::: l2 prepends the list l1 to the list l).

Scala Pattern Matching Enigma

Here's my attempt of the 3rd problem (P03) of the 99 Problems in Scala (http://aperiodic.net/phil/scala/s-99/):
import scala.annotation._
// Find the nth element of a list.
// nth(2, List(1, 1, 2, 3, 5, 8)) = 2
object P03 {
#tailrec def nth[A](n: Int, ls: List[A]): A = (n, ls) match {
case (0, h :: t :: Nil) => h
case (n, _ :: t) => nth(n - 1, t)
case _ => println(n); throw new IllegalArgumentException
}
The enigma is that this code prints -4 and throws an IllegalArgumentException
The solution of course is to change the first pattern to:
case (0, h :: _) => h
This now prints the correct answer 2
Question is Why? What is the subtle difference between:
case (0, h :: t :: Nil) => h
&
case (0, h :: _) => h
Thanks!
The difference is that h :: t :: Nil matches only a list with two elements (h and t, Nil is the marker for the end of a list (I'm not 100% sure it's the exact nomenclature)) while h :: _ matches every non empty list, ie a list that has at least one element, if you check the :: class you'll see:
final case class ::[B](private var hd: B, private[scala] var tl: List[B]) extends List[B]
Which has a head and a tail where the first is the first element of the list and the second is the rest, matching on h :: t :: Nil means getting the first element of the list, than the first of the tail and then there should be a Nil, matching on h :: _ means getting the head and then you don't care of what's left as long as there's a head.

Scala for-comprehension type inference

The next code
def f(chars: List[Char]): List[List[Char]] = chars match {
case Nil => List(Nil)
case x :: xs => for {
v <- f(xs)
} yield List(x) :: v
}
gives the error message
- type mismatch; found : List[List[Any]] required: List[List[Char]]
Please help me understand why 'for' chooses the most general Any instead of Char here? What topic in language spec should I read? Thanks.
The result, you are yielding is a mix of List[List[List[Char]]] and List[List[Char]]. Scala upcasts that to List[List[Any]]. For your case either of the following will do the job:
scala> def f(chars: List[Char]): List[List[Char]] = chars match {
| case Nil => List(Nil)
| case x :: xs => for {
| v <- f(xs)
| } yield x :: v
| }
f: (chars: List[Char])List[List[Char]]
scala> def f(chars: List[Char]): List[List[Char]] = chars match {
| case Nil => List(Nil)
| case x :: xs => for {
| v <- f(xs)
| } yield List(x) ++ v
| }
f: (chars: List[Char])List[List[Char]]
The problem is List(x) -- it needs to be x.
First, v iterates over the results of f(xs), and f returns List[List[Char]]. That means the result will be List[X], where X is the type returned by yield.
The type of v is List[Char], since it is iterating over the contents of f(xs). So we have to figure out the type of List(x) :: v, which is prepending a List[Char] on a List[Char]. It is not concatenating them: it is adding a list to a list containing only characters. The resulting list will have both Char and List[Char] in it.
Since the only type that satisfy both is Any, then X will be Any and the result of the for-comprehension List[Any].

Pattern matching and infinite streams

So, I'm working to teach myself Scala, and one of the things I've been playing with is the Stream class. I tried to use a naïve translation of the classic Haskell version of Dijkstra's solution to the Hamming number problem:
object LazyHammingBad {
private def merge(a: Stream[BigInt], b: Stream[BigInt]): Stream[BigInt] =
(a, b) match {
case (x #:: xs, y #:: ys) =>
if (x < y) x #:: merge(xs, b)
else if (y < x) y #:: merge(a, ys)
else x #:: merge(xs, ys)
}
val numbers: Stream[BigInt] =
1 #:: merge(numbers map { _ * 2 },
merge(numbers map { _ * 3 }, numbers map { _ * 5 }))
}
Taking this for a spin in the interpreter led quickly to disappointment:
scala> LazyHammingBad.numbers.take(10).toList
java.lang.StackOverflowError
I decided to look to see if other people had solved the problem in Scala using the Haskell approach, and adapted this solution from Rosetta Code:
object LazyHammingGood {
private def merge(a: Stream[BigInt], b: Stream[BigInt]): Stream[BigInt] =
if (a.head < b.head) a.head #:: merge(a.tail, b)
else if (b.head < a.head) b.head #:: merge(a, b.tail)
else a.head #:: merge(a.tail, b.tail)
val numbers: Stream[BigInt] =
1 #:: merge(numbers map {_ * 2},
merge(numbers map {_ * 3}, numbers map {_ * 5}))
}
This one worked nicely, but I still wonder how I went wrong in LazyHammingBad. Does using #:: to destructure x #:: xs force the evaluation of xs for some reason? Is there any way to use pattern matching safely with infinite streams, or do you just have to use head and tail if you don't want things to blow up?
a match {case x#::xs =>... is about the same as val (x, xs) = (a.head, a.tail). So the difference between the bad version and the good one, is that in that in the bad version, you're calling a.tail and b.tail right at the start, instead of just use them to build the tail of the resulting stream. Furthermore when you use them at the right of #:: (not pattern matching, but building the result, as in #:: merge(a.b.tail) you are not actually calling merge, that will be done only later, when accessing the tail of the returned Stream. So in the good version, a call to merge does not call tail at all. In the bad version, it calls it right at start.
Now if you consider numbers, or even a simplified version, say 1 #:: merge(numbers, anotherStream), when you call you call tail on that (as take(10) will), merge has to be evaluated. You call tail on numbers, which call merge with numbers as parameters, which calls tails on numbers, which calls merge, which calls tail...
By contrast, in super lazy Haskell, when you pattern match, it does barely any work. When you do case l of x:xs, it will evaluate l just enough to know whether it is an empty list or a cons.
If it is indeed a cons, x and xs will be available as two thunks, functions that will eventually give access, later, to content. The closest equivalent in Scala would be to just test empty.
Note also that in Scala Stream, while the tail is lazy, the head is not. When you have a (non empty) Stream, the head has to be known. Which means that when you get the tail of the stream, itself a stream, its head, that is the second element of the original stream, has to be computed. This is sometimes problematic, but in your example, you fail before even getting there.
Note that you can do what you want by defining a better pattern matcher for Stream:
Here's a bit I just pulled together in a Scala Worksheet:
object HammingTest {
// A convenience object for stream pattern matching
object #:: {
class TailWrapper[+A](s: Stream[A]) {
def unwrap = s.tail
}
object TailWrapper {
implicit def unwrap[A](wrapped: TailWrapper[A]) = wrapped.unwrap
}
def unapply[A](s: Stream[A]): Option[(A, TailWrapper[A])] = {
if (s.isEmpty) None
else {
Some(s.head, new TailWrapper(s))
}
}
}
def merge(a: Stream[BigInt], b: Stream[BigInt]): Stream[BigInt] =
(a, b) match {
case (x #:: xs, y #:: ys) =>
if (x < y) x #:: merge(xs, b)
else if (y < x) y #:: merge(a, ys)
else x #:: merge(xs, ys)
} //> merge: (a: Stream[BigInt], b: Stream[BigInt])Stream[BigInt]
lazy val numbers: Stream[BigInt] =
1 #:: merge(numbers map { _ * 2 }, merge(numbers map { _ * 3 }, numbers map { _ * 5 }))
//> numbers : Stream[BigInt] = <lazy>
numbers.take(10).toList //> res0: List[BigInt] = List(1, 2, 3, 4, 5, 6, 8, 9, 10, 12)
}
Now you just need to make sure that Scala finds your object #:: instead of the one in Stream.class whenever it's doing pattern matching. To facilitate that, it might be best to use a different name like #>: or ##:: and then just remember to always use that name when pattern matching.
If you ever need to match the empty stream, use case Stream.Empty. Using case Stream() will attempt to evaluate your entire stream there in the pattern match, which will lead to sadness.