Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

What's the reason of marking a recursive function as rec in F#?

I am not sure if this is a stupid question but I was going through the tutorial that comes with VS 2010 and there is a function like this:

let rec factorial n = if n=0 then 1 else n * factorial (n-1)

What's the reason of this recursive function to be marked with the rec keyword?

Is it so that the compiler is assured of it being recursive so can do certain optimizations?

What happens if you exclude it?

like image 750
Joan Venge Avatar asked Sep 17 '10 22:09

Joan Venge


People also ask

What is REC in F#?

Recursive functions - functions that call themselves - are identified explicitly in the F# language with the rec keyword. The rec keyword makes the name of the let binding available in its body. The following example shows a recursive function that computes the nth Fibonacci number using the mathematical definition.

How do you know if a function is recursive?

To find the nth term, for example, you need to know the previous term and the term before that one. This is how you can determine whether a particular function is recursive or not. If the function requires a previous term in the same sequence, then it is recursive.

What is recursive function in complexity theory?

The recursive functions are a class of functions on the natural numbers studied in computability theory, a branch of contemporary mathematical logic which was originally known as recursive function theory.

What is well defined recursive function?

"Well-defined" is a somewhat fuzzy term. But here, it seems that you want to ensure that a function that is defined at 1 and then you have a recursive definition explaining how to obtain f(n) from f(n−1) does in fact lead to a function whose domain is all the natural numbers.


2 Answers

This might be instructive:

let Main() =
    let f(x) = 
        printfn "original f: %d" x
    let f(x) =
    //let rec f(x) =
        printfn "entered new f: %d" x
        if x > 0 then
            f(x-1)
        else
            printfn "done"
    f(3)
Main()

That prints

entered new f: 3
original f: 2

Now if we comment out let and uncomment let rec, then it prints

entered new f: 3
entered new f: 2
entered new f: 1
entered new f: 0
done

So from that point of view, it's just about name binding; let rec puts the identifier in scope immediately (in this example, shadowing the previous f), whereas let puts the identifier in scope only after its body is defined.

The motivation for the rule does stem from interactions with type inference.

like image 175
Brian Avatar answered Sep 27 '22 15:09

Brian


According to Chris Smith (works on the F# team) -

It's to inform the type inference system to allow the function to be used as part of the type inference process. rec allows you to call the function before the type inference system has determined the function's type

like image 34
Russ Cam Avatar answered Sep 27 '22 17:09

Russ Cam