views:

231

answers:

4

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?

+4  A: 

According to the MSDN, it's only a syntatic necessity:

Recursive functions, functions that call themselves, are identified explicitly in the F# language. This makes the identifer that is being defined available in the scope of the function.

http://msdn.microsoft.com/en-us/library/dd233232.aspx

Gorkem Pacaci
+5  A: 

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

Russ Cam
Otherwise the type inference system would go into an infinite loop? If that's why, then makes sense.
Joan Venge
Really, is that all? Taking this point in, I wonder if I can write a recursive function *without* `rec` if I explicitly define all of the types... experiment time!
gnucom
Without `rec`, you'd also have to define the function itself beforehand. But you'd have to define the function first, since it wouldn't be available within its own scope. But first, you'd have to define the function. After you defined the function. Once the function was defined. Which would require defining the function. *ad infinitum.*
cHao
@cHao: Yeah this is what I was thinking as not doable.
Joan Venge
Baiscally it allows you to use it at the same time it is defined
BlackTigerX
@gnucom, cHao - all you need is the fix point function!
Freed
+3  A: 

It's necessary so that the function can be recursive. A non-rec function only knows about bindings at the place where it's defined, not after (so it doesn't know about itself).

Chuck
Thanks Chuck. What do you mean by bindings? Is it like scoping?
Joan Venge
@Joan Venge: a binding is basically a variable name and its associated value. In this case it means that you cannot use the function inside of itself, because it only gets bound to the name *after* the `let`. `let rec` makes the names that are being bound available *inside* the binding expression itself.
Jörg W Mittag
@Jorg, thanks that makes sense.
Joan Venge
+10  A: 

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.

Brian
That's a very educative example on binding, shadowing, and scoping :-).
Edgar Sánchez