Why is this function not tail recursive? - scala

I'm writing a simple contains method for a list like structure. I want it to be optimized for tail recursion but can't figure out why the compiler is complaining.
The Cons case is tail recursive but not the repeat case even though they're making the same call on the same data structure. Maybe I'm not understanding tail recursion properly. If someone could clear this up I would a grateful.
final def contains[B >: A](target: B): Boolean = this match{
case Empty => false
case Cons( h, t ) => h == target || t.contains( target )
case Repeat( _, l ) => l.contains( target )
}

A tail-recursive function is defined as one whose last statement is either returning a plain value or calling itself, and that has to be the only recursive call.
First, your function doesn't have recursive calls, because you are not calling contains function again. But, you are calling the contains method of another instance.
That can be solved, by moving the logic outside the class.
However, there is another common problem.
This: h == target || t.contains( target ) is not a tail-recursive call, since the last operation is not the call to contains but the or (||) executed with its result.
Here is how you may refactor it.
def contains[A](list: MyList[A])(target: A): Boolean = {
#annotation.tailrec
def loop(remaining: MyList[A]): Boolean =
remaining match {
case Empty => false
case Cons(h, t) => if (h == target) true else loop(remaining = t)
case Repeat(_, l) => loop(remaining = l)
}
loop(remaining = list)
}
If you still want the method on your class, you can forward it to call this helper function passing this as the initial value.

Related

Why does #tailrec not permit this seemingly tail recursive function?

The helper function here:
def zipWith[B]: (MyList[B], (A, B) => B) => MyList[B] = {
(list, function) => {
def helper: (MyList[B], MyList[A], MyList[B]) => MyList[B] = {
(consList, originalList, modList) =>
val wrapList = if (modList.isEmpty) list else modList
if (originalList.tail.isEmpty) consList ++ NewList(function(originalList.head, wrapList.head), EmptyList)
else helper(consList ++ NewList(function(originalList.head, wrapList.head), EmptyList),
originalList.tail,
modList.tail)
}
helper(EmptyList, this, list)
}
}
Is not recognised when using the #tailrec annotation.
Is this genuinely not tail-recursive? Could it cause a stack overflow error?
Or is this just a tail recursive function that the compiler is unable to optimise? Why?
helper doesn't call itself. It returns a function which eventually calls helper, but that's not the same thing.
In other words: helper is not tail-recursive because it is not even (direct-)recursive.
Scala can only optimize direct tail-recursion.
The problem is that the recursive code is creating a function value and then calling it, rather than calling a method directly.
If you change to method syntax it will be tail recursive.
#annotation.tailrec
def helper(consList: MyList[B], originalList: MyList[A], modList: MyList[B]): myList[B] = {
val wrapList = if (modList.isEmpty) list else modList
if (originalList.tail.isEmpty) consList ++ NewList(function(originalList.head, wrapList.head), EmptyList)
else helper(consList ++ NewList(function(originalList.head, wrapList.head), EmptyList),
originalList.tail,
modList.tail)
}

What is meant by not generating the answer lazily in this code?

I came across the following code:
/*
Unlike `take`, `drop` is not incremental. That is, it doesn't generate the
answer lazily. It must traverse the first `n` elements of the stream eagerly.
*/
#annotation.tailrec
final def drop(n: Int): Stream[A] = this match {
case Cons(_, t) if n > 0 => t().drop(n - 1)
case _ => this
}
/*
`take` first checks if n==0. In that case we need not look at the stream at all.
*/
def take(n: Int): Stream[A] = this match {
case Cons(h, t) if n > 1 => cons(h(), t().take(n - 1))
case Cons(h, _) if n == 1 => cons(h(), empty)
case _ => empty
}
Could someone explain what is meant by the comment:
Unlike take, drop is not incremental. That is, it doesn't generate the
answer lazily. It must traverse the first n elements of the stream eagerly.
To me, it looks like both the drop and take functions have to traverse the first n elements of the stream eagerly? What is it about the drop function that causes the first n elements to be eagerly traversed?
(Full code context here: https://github.com/fpinscala/fpinscala/blob/master/answers/src/main/scala/fpinscala/laziness/Stream.scala)
The definition for Cons is:
case class Cons[+A](h: () => A, t: () => Stream[A]) extends Stream[A]
Notice that the second parameter, t, takes a function (from Unit to Stream[A]), not the evaluation of that function. This is not evaluated until required, and hence is lazy, as is the take method that calls it.
Compare this to drop which calls t() itself rather than passing it into the Cons, forcing the immediate evaluation.
The key point is that cons is lazy. That is if the recursion is inside of cons, the recursion won't happen until the tail of the generated list is actually accessed. Whereas if the recursion is outside, it happens right away.
So drop is eager because the recursion is not inside a cons (or any other lazy construct).

Curried function evaluates all arguements

I'm trying to figure out why my curried function operates in the following way. I built the function ensure to take a more function approach instead of multiple if-then statements that would accomplish the same thing.
I discovered a bug today will running some tests where if the condition in the first ensure function e.g. ensure(contents.hasNext && acc != null) is true, the false condition or second arguement still gets evaluated and becomes the overriding function.
I can fix the problem if I simple change this: ensure(contents.hasNext) to this: ensure(contents.hasNext && acc == null) but i'm struggling with WHY this is happening.
Is there a more obvious (or just better) solution to this?
def ensure[T](f: => Boolean)(truth: => T, lie: T) = if (f) truth else lie
def lines(): Stream[String] = {
def matchLine(text: String, acc: String): Stream[String] = text match {
...
case NewLine(string) =>
ensure(contents.hasNext && acc != null)(acc +: matchLine(contents.next, string),
ensure(contents.hasNext)(matchLine(contents.next, string), acc +: string +: empty))
...
}
ensure(contents.hasNext)(matchLine(contents.next, null), empty)
}
(truth: => T, lie: T)
This means that the expression given for the truth parameter, will be evaluated each time that truth is used within your function (and only then), while lie will be executed exactly once before your function starts executing. In other words: truth is passed by name and lie isn't. To achieve the behaviour you want, you'd need to pass both by name (on the other passing the condition by name is not really necessary since it will be evaluated exactly once at the beginning of the function in all cases):
ensure[T](f: Boolean)(truth: => T, lie: => T) = if (f) truth else lie
That said, I wouldn't agree that replacing if-then-else expressions with a function that's basically a wrapper around if-then-else, makes your code more functional.

Implementing ifTrue, ifFalse, ifSome, ifNone, etc. in Scala to avoid if(...) and simple pattern matching

In Scala, I have progressively lost my Java/C habit of thinking in a control-flow oriented way, and got used to go ahead and get the object I'm interested in first, and then usually apply something like a match or a map() or foreach() for collections. I like it a lot, since it now feels like a more natural and more to-the-point way of structuring my code.
Little by little, I've wished I could program the same way for conditions; i.e., obtain a Boolean value first, and then match it to do various things. A full-blown match, however, does seem a bit overkill for this task.
Compare:
obj.isSomethingValid match {
case true => doX
case false => doY
}
vs. what I would write with style closer to Java:
if (obj.isSomethingValid)
doX
else
doY
Then I remembered Smalltalk's ifTrue: and ifFalse: messages (and variants thereof). Would it be possible to write something like this in Scala?
obj.isSomethingValid ifTrue doX else doY
with variants:
val v = obj.isSomethingValid ifTrue someVal else someOtherVal
// with side effects
obj.isSomethingValid ifFalse {
numInvalid += 1
println("not valid")
}
Furthermore, could this style be made available to simple, two-state types like Option? I know the more idiomatic way to use Option is to treat it as a collection and call filter(), map(), exists() on it, but often, at the end, I find that I want to perform some doX if it is defined, and some doY if it isn't. Something like:
val ok = resultOpt ifSome { result =>
println("Obtained: " + result)
updateUIWith(result) // returns Boolean
} else {
numInvalid += 1
println("missing end result")
false
}
To me, this (still?) looks better than a full-blown match.
I am providing a base implementation I came up with; general comments on this style/technique and/or better implementations are welcome!
First: we probably cannot reuse else, as it is a keyword, and using the backticks to force it to be seen as an identifier is rather ugly, so I'll use otherwise instead.
Here's an implementation attempt. First, use the pimp-my-library pattern to add ifTrue and ifFalse to Boolean. They are parametrized on the return type R and accept a single by-name parameter, which should be evaluated if the specified condition is realized. But in doing so, we must allow for an otherwise call. So we return a new object called Otherwise0 (why 0 is explained later), which stores a possible intermediate result as a Option[R]. It is defined if the current condition (ifTrue or ifFalse) is realized, and is empty otherwise.
class BooleanWrapper(b: Boolean) {
def ifTrue[R](f: => R) = new Otherwise0[R](if (b) Some(f) else None)
def ifFalse[R](f: => R) = new Otherwise0[R](if (b) None else Some(f))
}
implicit def extendBoolean(b: Boolean): BooleanWrapper = new BooleanWrapper(b)
For now, this works and lets me write
someTest ifTrue {
println("OK")
}
But, without the following otherwise clause, it cannot return a value of type R, of course. So here's the definition of Otherwise0:
class Otherwise0[R](intermediateResult: Option[R]) {
def otherwise[S >: R](f: => S) = intermediateResult.getOrElse(f)
def apply[S >: R](f: => S) = otherwise(f)
}
It evaluates its passed named argument if and only if the intermediate result it got from the preceding ifTrue or ifFalse is undefined, which is exactly what is wanted. The type parametrization [S >: R] has the effect that S is inferred to be the most specific common supertype of the actual type of the named parameters, such that for instance, r in this snippet has an inferred type Fruit:
class Fruit
class Apple extends Fruit
class Orange extends Fruit
val r = someTest ifTrue {
new Apple
} otherwise {
new Orange
}
The apply() alias even allows you to skip the otherwise method name altogether for short chunks of code:
someTest.ifTrue(10).otherwise(3)
// equivalently:
someTest.ifTrue(10)(3)
Finally, here's the corresponding pimp for Option:
class OptionExt[A](option: Option[A]) {
def ifNone[R](f: => R) = new Otherwise1(option match {
case None => Some(f)
case Some(_) => None
}, option.get)
def ifSome[R](f: A => R) = new Otherwise0(option match {
case Some(value) => Some(f(value))
case None => None
})
}
implicit def extendOption[A](opt: Option[A]): OptionExt[A] = new OptionExt[A](opt)
class Otherwise1[R, A1](intermediateResult: Option[R], arg1: => A1) {
def otherwise[S >: R](f: A1 => S) = intermediateResult.getOrElse(f(arg1))
def apply[S >: R](f: A1 => S) = otherwise(f)
}
Note that we now also need Otherwise1 so that we can conveniently passed the unwrapped value not only to the ifSome function argument, but also to the function argument of an otherwise following an ifNone.
You may be looking at the problem too specifically. You would probably be better off with the pipe operator:
class Piping[A](a: A) { def |>[B](f: A => B) = f(a) }
implicit def pipe_everything[A](a: A) = new Piping(a)
Now you can
("fish".length > 5) |> (if (_) println("Hi") else println("Ho"))
which, admittedly, is not quite as elegant as what you're trying to achieve, but it has the great advantage of being amazingly versatile--any time you want to put an argument first (not just with booleans), you can use it.
Also, you already can use options the way you want:
Option("fish").filter(_.length > 5).
map (_ => println("Hi")).
getOrElse(println("Ho"))
Just because these things could take a return value doesn't mean you have to avoid them. It does take a little getting used to the syntax; this may be a valid reason to create your own implicits. But the core functionality is there. (If you do create your own, consider fold[B](f: A => B)(g: => B) instead; once you're used to it the lack of the intervening keyword is actually rather nice.)
Edit: Although the |> notation for pipe is somewhat standard, I actually prefer use as the method name, because then def reuse[B,C](f: A => B)(g: (A,B) => C) = g(a,f(a)) seems more natural.
Why don't just use it like this:
val idiomaticVariable = if (condition) {
firstExpression
} else {
secondExpression
}
?
IMO, its very idiomatic! :)

Issues with maps and their entries in Scala

I have a recursive function that takes a Map as single parameter. It then adds new entries to that Map and calls itself with this larger Map. Please ignore the return values for now. The function isn't finished yet. Here's the code:
def breadthFirstHelper( found: Map[AIS_State,(Option[AIS_State], Int)] ): List[AIS_State] = {
val extension =
for(
(s, v) <- found;
next <- this.expand(s) if (! (found contains next) )
) yield (next -> (Some(s), 0))
if ( extension.exists( (s -> (p,c)) => this.isGoal( s ) ) )
List(this.getStart)
else
breadthFirstHelper( found ++ extension )
}
In extension are the new entries that shall get added to the map. Note that the for-statement generates an iterable, not a map. But those entries shall later get added to the original map for the recursive call. In the break condition, I need to test whether a certain value has been generated inside extension. I try to do this by using the exists method on extension. But the syntax for extracting values from the map entries (the stuff following the yield) doesn't work.
Questions:
How do I get my break condition (the boolean statement to the if) to work?
Is it a good idea to do recursive work on a immutable Map like this? Is this good functional style?
When using a pattern-match (e.g. against a Tuple2) in a function, you need to use braces {} and the case statement.
if (extension.exists { case (s,_) => isGoal(s) } )
The above also uses the fact that it is more clear when matching to use the wildcard _ for any allowable value (which you subsequently do not care about). The case xyz gets compiled into a PartialFunction which in turn extends from Function1 and hence can be used as an argument to the exists method.
As for the style, I am not functional programming expert but this seems like it will be compiled into a iterative form (i.e. it's tail-recursive) by scalac. There's nothing which says "recursion with Maps is bad" so why not?
Note that -> is a method on Any (via implicit conversion) which creates a Tuple2 - it is not a case class like :: or ! and hence cannot be used in a case pattern match statement. This is because:
val l: List[String] = Nil
l match {
case x :: xs =>
}
Is really shorthand/sugar for
case ::(x, xs) =>
Similarly a ! b is equivalent to !(a, b). Of course, you may have written your own case class ->...
Note2: as Daniel says below, you cannot in any case use a pattern-match in a function definition; so while the above partial function is valid, the following function is not:
(x :: xs) =>
This is a bit convoluted for me to follow, whatever Oxbow Lakes might think.
I'd like first to clarify one point: there is no break condition in for-comprehensions. They are not loops like C's (or Java's) for.
What an if in a for-comprehension means is a guard. For instance, let's say I do this:
for {i <- 1 to 10
j <- 1 to 10
if i != j
} yield (i, j)
The loop isn't "stopped" when the condition is false. It simply skips the iterations for which that condition is false, and proceed with the true ones. Here is another example:
for {i <- 1 to 10
j <- 1 to 10
if i % 2 != 0
} yield (i, j)
You said you don't have side-effects, so I can skip a whole chapter about side effects and guards on for-comprehensions. On the other hand, reading a blog post I made recently on Strict Ranges is not a bad idea.
So... give up on break conditions. They can be made to work, but they are not functional. Try to rephrase the problem in a more functional way, and the need for a break condition will be replaced by something else.
Next, Oxbow is correct in that (s -> (p,c) => isn't allowed because there is no extractor defined on an object called ->, but, alas, even (a :: b) => would not be allowed, because there is no pattern matching going on in functional literal parameter declaration. You must simply state the parameters on the left side of =>, without doing any kind of decomposition. You may, however, do this:
if ( extension.exists( t => val (s, (p,c)) = t; this.isGoal( s ) ) )
Note that I replaced -> with ,. This works because a -> b is a syntactic sugar for (a, b), which is, itself, a syntactic sugar for Tuple2(a, b). As you don't use neither p nor c, this works too:
if ( extension.exists( t => val (s, _) = t; this.isGoal( s ) ) )
Finally, your recursive code is perfectly fine, though probably not optimized for tail-recursion. For that, you either make your method final, or you make the recursive function private to the method. Like this:
final def breadthFirstHelper
or
def breadthFirstHelper(...) {
def myRecursiveBreadthFirstHelper(...) { ... }
myRecursiveBreadthFirstHelper(...)
}
On Scala 2.8 there is an annotation called #TailRec which will tell you if the function can be made tail recursive or not. And, in fact, it seems there will be a flag to display warnings about functions that could be made tail-recursive if slightly changed, such as above.
EDIT
Regarding Oxbow's solution using case, that's a function or partial function literal. It's type will depend on what the inference requires. In that case, because that's that exists takes, a function. However, one must be careful to ensure that there will always be a match, otherwise you get an exception. For example:
scala> List(1, 'c') exists { case _: Int => true }
res0: Boolean = true
scala> List(1, 'c') exists { case _: String => true }
scala.MatchError: 1
at $anonfun$1.apply(<console>:5)
... (stack trace elided)
scala> List(1, 'c') exists { case _: String => true; case _ => false }
res3: Boolean = false
scala> ({ case _: Int => true } : PartialFunction[AnyRef,Boolean])
res5: PartialFunction[AnyRef,Boolean] = <function1>
scala> ({ case _: Int => true } : Function1[Int, Boolean])
res6: (Int) => Boolean = <function1>
EDIT 2
The solution Oxbow proposes does use pattern matching, because it is based on function literals using case statements, which do use pattern matching. When I said it was not possible, I was speaking of the syntax x => s.