Какова причина маркировки рекурсивной функции как rec в F #?

Я не уверен, что это глупый вопрос, но я прошел учебник, который поставляется с VS 2010, и существует такая функция:

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

Какова причина, по которой эта рекурсивная функция должна быть отмечена ключевым словом rec?

Это значит, что компилятор уверен в том, что он рекурсивный, поэтому можно сделать некоторые оптимизации?

Что произойдет, если вы его исключите?

Ответ 1

Это может быть поучительно:

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()

Что печатает

entered new f: 3
original f: 2

Теперь, если мы прокомментируем let и раскомментируем let rec, тогда он печатает

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

Итак, с этой точки зрения, это просто привязка имени; let rec немедленно помещает идентификатор в область видимости (в этом примере затеняет предыдущий f), тогда как let помещает идентификатор в область видимости только после определения его тела.

Мотивация правила основывается на взаимодействиях с типом вывода.

Ответ 2

По словам Криса Смита (работает над командой F #) -

Он должен сообщить системе вывода типа, чтобы позволить использовать эту функцию как часть процесса вывода типа. rec позволяет вызывать функцию до того, как система вывода типа определит тип функции

Ответ 3

Согласно MSDN, это только синтаксическая необходимость:

Рекурсивные функции, функции, которые называют себя, идентифицированы явно на языке F #. Эта делает идентификатор, который определенных в объеме функция.

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

Ответ 4

Необходимо, чтобы функция могла быть рекурсивной. Функция не rec знает только о привязках в том месте, где она была определена, а не после (поэтому она не знает о себе).

Ответ 5

Какова причина, по которой эта рекурсивная функция должна быть отмечена ключевым словом rec?

Чтобы сообщить компилятору, что любое использование имени функции внутри тела функции ссылается на него рекурсивно, а не на ранее определенное значение с тем же именем.

Это значит, что компилятор уверен в том, что он рекурсивный, поэтому можно сделать некоторые оптимизации?

Нет.

Что произойдет, если вы его исключите?

Вы теряете способность функции, которую вы определяете, ссылаться на себя в своем теле функции и получать возможность ссылаться на ранее определенные значения с тем же именем.