F# recursive function arguments and stack overflow - recursion

I am somewhat new to F#, and I came across some strange behaviour when I was working with some recursive functions. I have two different versions of it below:
Version 1:
This causes a stack overflow, though it seems that it shouldn't (at least to my noob eyes)
let rec iMake acc =
match acc with
| 10 -> 100
| _ -> iMake acc+1
Version2:
This one works as I would expect it to.
let rec iMake acc =
match acc with
| 10 -> 100
| _ -> iMake (acc+1)
The only difference is that version 2 puts the acc+1 expression into parenthesis. So my question is, why does the first version not work, but the second one does? Does this mean that I should put all of my function arguments into parenthesis to avoid this type of stuff in the future ?

Function call has higher precedence than binary operator +. So the first function actually works like:
let rec iMake acc =
match acc with
| 10 -> 100
| _ -> (iMake acc)+1

Related

Avoid stackoverflow when recursively dismantling a string

I'm working on a solution for a problem for the advent of code 2018 (spoiler alert) where I need a function which takes a string (or a char list) and removes every pair of chars when they react. The exercise describes two chars, or "elements" in a "polymer", reacting when they are the same letter but only differ in case; so starting out with AbBc would leave you with Ac. Keep in mind that after a reaction two chars could end up next to each other, where they weren't before, and cause a new reaction.
I thought I could solve this by using a recursive function which only deals with the first two chars and recursively calls itself, but since the input string is quite large, this causes a stackoverflow exception:
let rec react polymer =
match polymer with
| [] -> []
| [x] -> [x]
| head::tail ->
let left = head
let right = List.head tail
let rest = List.tail tail
// 'reacts' takes two chars and
// returns 'true' when they react
match reacts left right with
// when reacts we go further with
// the rest as these two chars are
// obliterated
| true -> react rest
// no reaction means the left char
// remains intact and the right one
// could react with the first char
// of the rest
| false -> [left] # react tail
Then, just trying to solve the exercise to have a right answer to unit test against, I tried to do it imperatively, but that got messy real quick and now I'm kinda stuck. I'm teaching myself f# so any pointers are welcome. Can anyone solve this in a functional manner?
You can avoid stack overflow by rewriting your function to use tail recursion, which just means that the recursive call should be the last operation to execute.
When you do [left] # react tail you first make a recursive call, and then append [left] to the result of that. That means it has to keep the current function context, called a stack frame, around while it executes the recursive call, and if that recurses as well the stack frames add up until you get a stack overflow. But if there's no more work to be done in the current function context, the stack frame can be released (or reused), hence no stack overflow.
You can make it tail recursive by adding another function argument, conventionally called acc since it "accumulates" values. Instead of adding left to the return value of the recursive call we add it to the accumulator and pass that along. Then when we exhaust the input, we return the accumulator instead of the empty list.
I've also taken the liberty of the append, [left] # ..., as a cons, left::..., since the latter is much more efficient than the former. I've also moved left, right and rest to the pattern, since that's much neater and safer. You should generally avoid using List.head and List.tail since they fail on empty lists and are bugs just waiting to happen.
let rec react acc polymer =
match polymer with
| [] -> acc
| [x] -> x::acc
| left::right::rest ->
match reacts left right with
| true -> react acc rest
| false -> react (left::acc) (right::rest)
You could also use a guard instead of nested matches (which should really have been an if anyway):
let rec react acc polymer =
match polymer with
| [] ->
acc
| [x] ->
x::acc
| left::right::rest when reacts left right ->
react acc rest
| left::rest ->
react (left::acc) rest

Recursion in F# Example

I've started learning F# and following in the footsteps of example problems I've written my own statement. It's simple enough, but I'm getting an error that doesn't exist in similar recursion examples.
My function replace takes a list of integers, an swapVal integer and a newVal integer. It then recurses through the list and changes any 'swapVal' to 'newVal'.
let original = [1;3;1;4;1;6;1;9]
let rec replace list origVal newVal =
match list with //look at list
| [] -> [] //when ls empty, return empty list
| head :: tail when head = origVal -> newVal :: replace tail origVal newVal
//when list is a head attached to a tail, if head = origVal,
//call replace on tail and appead the newVal
|_ :: tail -> replace tail origVal newVal
//head not equal to original value, call replace tail and return result
Calling replace original 1 5 I'm getting the following error Script.fsx(144,9): error FS0039: The value or constructor 'original' is not defined. Searching online like here hasn't turned up any solutions. Even O'Reilly's programming F# says that it could be a scoping problem, but there's no way that scope is my error.
I feel like it could be that f# is typing my arguments incorrectly, but I don't know enough about f# to know how it types. I would cast the arguments to make sure, but I read that it's not possible.
Does anyone see any immediate errors?

How can I get this function to be tail-recursive?

I'm still trying to implement 2-3 finger trees and I made good progress (repository). While doing some benchmarks I found out that my quite basic toList results in a StackOverflowException when the tree ist quite large. At first I saw an easy fix and made it tail-recursive.
Unfortunately, it turned out that toList wasn't the culprit but viewr was:
/// Return both the right-most element and the remaining tree (lazily).
let rec viewr<'a> : FingerTree<'a> -> View<'a> = function
| Empty -> Nil
| Single x -> View(x, lazyval Empty)
| Deep(prefix, deeper, One x) ->
let rest = lazy (
match viewr deeper.Value with
| Nil ->
prefix |> Digit.promote
| View (node, lazyRest) ->
let suffix = node |> Node.toList |> Digit.ofList
Deep(prefix, lazyRest, suffix)
)
View(x, rest)
| Deep(prefix, deeper, Digit.SplitLast(shorter, x)) ->
View(x, lazy Deep(prefix, deeper, shorter))
| _ -> failwith Messages.patternMatchImpossible
Looking for the only recursive call it is obvious that this is is not tail-recursive. Somehow I hoped this problem wouldn't exist because that call is wrapped in a Lazy which IMHO is similar to a continuation.
I heard and read of continuations but so far never (had to) use(d) them. I guess here I really need to. I've been staring at the code for quite some time, putting function parameters here and there, calling them other places… I'm totally lost!
How can this be done?
Update: The calling code looks like this:
/// Convert a tree to a list (left to right).
let toList tree =
let rec toList acc tree =
match viewr tree with
| Nil -> acc
| View(head, Lazy tail) -> tail |> toList (head::acc)
toList [] tree
Update 2: The code that caused the crash is this one.
let tree = seq {1..200000} |> ConcatDeque.ofSeq
let back = tree |> ConcatDeque.toList
The tree get built fine, I checked and it is only 12 levels deep. It's the call in line 2 that triggered the overflow.
Update 3: kvb was right, that pipe issue I ran into before has something to do with this. Re-testing the cross product of debug/release and with/without pipe it worked in all but one case: debug mode with the pipe operator crashed. The behavior was the same for 32 vs. 64 bit.
I'm quite sure that I was running release mode when posting the question but today it's working. Maybe there was some other factor… Sorry about that.
Although the crash is solved, I'm leaving the question open out of theoretical interest. After all, we're here to learn, aren't we?
So let me adapt the question:
From looking at the code, viewr is definitely not tail-recursive. Why doesn't it always blow up and how would one rewrite it using continuations?
Calling viewr never results in an immediate recursive call to viewr (the recursive call is protected by lazy and is not forced within the remainder of the call to viewr), so there's no need to make it tail recursive to prevent the stack from growing without bound. That is, a call to viewr creates a new stack frame which is then immediately popped when viewr's work is done; the caller can then force the lazy value resulting in a new stack frame for the nested viewr call, which is then immediately popped again, etc., so repeating this process doesn't result in a stack overflow.

OCaml while true do loop

I have the following code:
let a = 1 in
while a<10 do
let a = a+1 in
done
Printf.printf "the number is now %d\n" a
The interpreter is complaining about line 4, which is done and I have no idea what is wrong here.
I understand that OCaml is a functional language and the variables are immutable. I should not try to change the value of a here.
But still, there is a while true do .. done loop in OCaml. I hope you get the idea of what I am trying to do here. How shall I modify the code to do this job with while true do .. done?
I am very new to functional programming. Please teach me the right way to get started with it. I find myself stuck in the deadlock of thinking imperatively.
The let ... in construct expects another expression behind. You can, for example use the () value (which basically means "nothing")
So the code
let a = 1 in
while a<10 do
let a = a+1 in
()
done
Printf.printf "the number is now %d\n" a
It will compile. But it will loop indefinitely because the a defined as 1 at start is different than the a declared as a+1.
Both are constant different values on different scopes, and a declaration inside the body of a while is limited to that occurence of the body.
You may get what you want by specifying a as mutable using the ref function and its handlers:
let a = ref 1 in
while !a < 10 do
a := !a + 1
done
Printf.printf "the number is now %d\n" !a
Note that you loose all the benefits of FP by using a while loop and mutable values.
To do it in a functionnal manner, you can use a recursive function:
let rec f a =
if a < 10
then f (a+1)
else a
in
let a = f 1 in
Printf.printf "the number is now %d\n" a
This one is the true right manner to do the job. If you want to do FP, avoid at all costs to use a while loop.

Opa: What Is the Fastest Way to Reverse a String?

What is the most performant way to implement a "reverse a string" function in Opa?
I am aware of String.reverse(). It does get the job done, but its source code is bound to some external function. I want to understand what the best (fastest) tools are for reordering a string.
So, for example, this works, but isn't particularly fast:
reverse(s:string) =
p = parser
| x=(.) xs=(.*) -> Text.concat(reverse(Text.to_string(xs)), x)
| x=(.*) -> x
Parser.parse(p, s)
How can I make this perform better?
Edit: Another Implementation Based on akoprowski's Answer
I think this is what he has in mind. This one is much faster than the parser version, but the built-in String.reverse is the way to go if all you need to do is reverse a string.
reverse_list(l:list(string)):list(string) =
match l with
| [x|xs] -> reverse_list(xs) ++ [x]
| _ -> []
reverse_string(s:string) =
string_list = List.init((i -> String.get(i, s)), String.length(s))
String.flatten(reverse_list(string_list))
Edit: The Above Implementation Is Not Ideal
Check out the accepted answer for a better option.
Why don't you want to use String.reverse? (which is the preferred way of reversing a string). Or is that just an exercise?
I'd suggest using List.init to generate a list of characters, String.get (to get n'th character of the string) and String.flatten to convert a list of characters back to a string.
That should be faster than the parsing-based approach, which btw. has quadratic complexity so no wonder it's slow.
Edit: the solution I had in mind:
reverse_string(s:string) =
n = String.length(s)
rev_list = List.init((i -> String.get(n - i - 1, s)), n)
String.flatten(rev_list)

Resources