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.
Related
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.
I'm trying to sum the values of the pairs that have the same character, but when printing, i get List((),())
here's my code
var lstA = List(("a",1),("b",2))
var lstB = List(("a",3), ("b",4))
val k = lstA.map(a => lstB.foreach(b => {
if(b._1 == a._1) (a._1, a._2+b._2) else a
}))
println(k)
of course there are better ways to do this, but I just want to know why this isn't working.
when debugging and evaluating the line if(b._1 == a._1) (a._1, a._2+b._2) else a i get the values of pairs as expected however when printing the list k is empty
The short and not entirely accurate answer is because foreach doesn't return anything. Actually, though, it does return something. Here is the signature:
def foreach[U](f: (A) ⇒ U): Unit
It returns a Unit type, which is used as a signal that the function has side-effects. From the documentation, the f parameter is:
the function that is applied for its side-effect to every element. The
result of function f is discarded.
So the function is expected to have a side effect. This could be something like println.
I have superficially read a couple of blog articles/Wikipedia about continuation-passing style. My high-level goal is to find a systematic technique to make any recursive function (or, if there are restrictions, being aware of them) tail-recursive. However, I have trouble articulating my thoughts and I'm not sure if what my attempts of it make any sense.
For the purpose of the example, I'll propose a simple problem. The goal is, given a sorted list of unique characters, to output all possible words made out of these characters in alphabetical order. For example, sol("op".toList, 3) should return ooo,oop,opo,opp,poo,pop,ppo,ppp.
My recursive solution is the following:
def sol(chars: List[Char], n: Int) = {
def recSol(n: Int): List[List[Char]] = (chars, n) match {
case (_ , 0) => List(Nil)
case (Nil, _) => Nil
case (_ , _) =>
val tail = recSol(n - 1)
chars.map(ch => tail.map(ch :: _)).fold(Nil)(_ ::: _)
}
recSol(n).map(_.mkString).mkString(",")
}
I did try to rewrite this by adding a function as a parameter but I did not manage to make something I was convinced to be tail-recursive. I prefer not including my attempt(s) in the question as I'm ashamed of their naiveness, so please excuse me for this.
Therefore the question is basically: how would the function above be written in CPS ?
Try that:
import scala.annotation.tailrec
def sol(chars: List[Char], n: Int) = {
#tailrec
def recSol(n: Int)(cont: (List[List[Char]]) => List[List[Char]]): List[List[Char]] = (chars, n) match {
case (_ , 0) => cont(List(Nil))
case (Nil, _) => cont(Nil)
case (_ , _) =>
recSol(n-1){ tail =>
cont(chars.map(ch => tail.map(ch :: _)).fold(Nil)(_ ::: _))
}
}
recSol(n)(identity).map(_.mkString).mkString(",")
}
The first order of business in performing the CPS transform is deciding on a representation for continuations. We can think of continuations as a suspended computation with a "hole". When the hole is filled in with a value, the remainder of the computation can be computed. So functions are a natural choice for representing continuations, at least for toy examples:
type Cont[Hole,Result] = Hole => Result
Here Hole represents the type of the hole that needs to be filled in, and Result represents the type of value the computation ultimately computes.
Now that we have a way to represent continuations, we can worry about the CPS transform itself. Basically, this involves the following steps:
The transformation is applied recursively to an expression, stopping at "trivial" expressions / function calls. In this context, "trivial" includes functions defined by Scala (since they are not CPS-transformed, and thus do not have a continuation parameter).
We need to add a parameter of type Cont[Return,Result] to each function, where Return is the return type of the untransformed function and Result is the type of the ultimate result of the computation as a whole. This new parameter represents the current continuation. The return type for the transformed function is also changed to Result.
Every function call needs to be transformed to accommodate the new continuation parameter. Everything after the call needs to be put into a continuation function, which is then added to the parameter list.
For example, a function:
def f(x : Int) : Int = x + 1
becomes:
def fCps[Result](x : Int)(k : Cont[Int,Result]) : Result = k(x + 1)
and
def g(x : Int) : Int = 2 * f(x)
becomes:
def gCps[Result](x : Int)(k : Cont[Int,Result]) : Result = {
fCps(x)(y => k(2 * y))
}
Now gCps(5) returns (via currying) a function that represents a partial computation. We can extract the value from this partial computation and use it by supplying a continuation function. For example, we can use the identity function to extract the value unchanged:
gCps(5)(x => x)
// 12
Or, we can print it by using println instead:
gCps(5)(println)
// prints 12
Applying this to your code, we obtain:
def solCps[Result](chars : List[Char], n : Int)(k : Cont[String, Result]) : Result = {
#scala.annotation.tailrec
def recSol[Result](n : Int)(k : Cont[List[List[Char]], Result]) : Result = (chars, n) match {
case (_ , 0) => k(List(Nil))
case (Nil, _) => k(Nil)
case (_ , _) =>
recSol(n - 1)(tail =>
k(chars.map(ch => tail.map(ch :: _)).fold(Nil)(_ ::: _)))
}
recSol(n)(result =>
k(result.map(_.mkString).mkString(",")))
}
As you can see, although recSol is now tail-recursive, it comes with the cost of building a more complex continuation at each iteration. So all we've really done is trade space on the JVM's control stack for space on the heap -- the CPS transform does not magically reduce the space complexity of an algorithm.
Also, recSol is only tail-recursive because the recursive call to recSol happens to be the first (non-trivial) expression recSol performs. In general, though, recursive calls would be take place inside a continuation. In the case where there is one recursive call, we can work around that by transforming only calls to the recursive function to CPS. Even so, in general, we would still just be trading stack space for heap space.
My assignment is to write a custom repeat control structure that can be used like this:
var i = 0
repeat {
i = i + 1
}(i > 5)
I currently have the following code for that:
def repeat(f: => Unit): ((=> Boolean) => Unit) = {
(x) => {
while (x) f
}
}
When running this, it seems f (i = i + 1) is never executed.
I have to be honest, I'm not entirely sure what the current type of x is. It's clearly not correct, but I don't have enough knowledge to know where to go from here.
I used to have this:
def repeat(f: => Unit): ((=> Boolean) => Void) = {
(x: (=> Boolean)) => {
while (x) f
}
}
Although this is apparently incorrect Scala, I think it demonstrates my intent better.
I'm sorry if my question is a bit broad/demonstrates effortlessness, but the concept of by-name parameters is very new to me and not explained in my book (Programming in Scala) beyond the basics.
You should also be aware that Scala supports multiple parameter lists. So you could
def compare(a: Int, b: Int)(p: (Int,Int) => Boolean) = p(a,b)
and then write
compare(5,2)(_ > _)
This type of strategy will simplify your logic.
Also, you have your comparison backwards. i starts out at 0 and your loop condition is i > 5, which it is not.
A few extra notes: => X means "compute an X each time one is needed", so ((=> Boolean) => Unit) takes something that will compute a Boolean as needed (and i > 5 can do that, if the check is performed each time, which it will be). (=> Boolean) => Unit means a function that takes as input something that produces Booleans and gives no output. (Well, strictly speaking, Unit type is an output, namely (), which is done for consistency. But it serves the same role as void.)
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.