Search code examples
loopsrecursionsmlsmlnjml

Standard ML running multiple functions in a loop (Using recursion or any other means)


I have defined three different functions that will perform calculations and return a value. These functions will consistently be redefining a variable until a specific condition is reached. I am having issues getting these to run in a "loop" scenario. I know functional languages are not best for performing loops and you should use recursion...but I am having a hard time wrapping my head around how to perform this.

I will make some real simple arbitrary functions to explain my situation.

fun add_them (a,b) =
    a+b;

fun substract_them (c,d) =
    c-d;

fun add_them2 (e,f) =
    e-f;

val a = 5;
val b = 7;
val c = 10;
val d = 1;

val a = add_them (a,b);
val d = add_them2 (c,d);

So let's say I want to run the last two lines a 1000 times. So Val A and Val D will keep getting added up to a huge number. Now I could literally copy and paste those two lines a 1000 times and get the result I want..but this of course defeats the purpose of programming :)

I was trying to create a loop that I can throw these two functions in. I was coming up with something like below, but I would have no idea how to incorporate these two. Perhaps I am going at this completely backwards.

fun whileloop (x,a) =
    if (a<1)
    then x 
    else whileloop(x+1,a-1);

So my goal was to insert those above val a and val d expressions into another function using recursion and run it a certain amount of times. Any help would be much appreciated.


Solution

  • A function that simply iterates another function n times is given in my answer here. But it sounds like you want to apply a given function n times to a seed, like so:

    f (f (f (f ... (f x) ... )))
    

    That can be accomplished by the following function:

    fun repeat n f x = if n = 0 then x else repeat (n-1) f (f x)
    

    For example,

    val n = repeat 20 (fn => n + 1) 0
    

    results in 20.

    Or perhaps you want to repeat based on a condition instead of a count:

    fun repeatWhile p f x = if p x then repeatWhile p f (f x) else x
    

    For example,

    val n = repeatWhile (fn x => x > 0) (fn x => x - 1) 20
    

    returns 0.

    Both functions are polymorphic, so also work with tuples. For example:

    val (x, y) = repeatWhile (fn (a, b) => a > 0) (fn (a, b) => (a-1, b+1)) (20, 0)
    

    returns (0, 20).

    If you dislike using two separate function parameters for condition and "action", you can also combine them by having it return a pair:

    fun repeatWhile2 f x =
        let val (c, y) = f x in if c then repeatWhile2 f y else x end
    

    Then:

    repeatWhile (fn (a, b) => (a > 0, (a-1, b+2))) (20, 0)