В чем причина маркировки рекурсивной функции как rec в F #? - PullRequest
15 голосов
/ 18 сентября 2010

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

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

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

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

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

Ответы [ 5 ]

28 голосов
/ 18 сентября 2010

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

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 помещает идентификатор в область только после определения его тела.

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

11 голосов
/ 18 сентября 2010

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

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

8 голосов
/ 18 сентября 2010

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

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

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

6 голосов
/ 30 декабря 2010

В чем причина того, что эта рекурсивная функция помечена ключевым словом rec?

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

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

Количество

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

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

5 голосов
/ 18 сентября 2010

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...