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
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.