Да, если компилятор испускает команду вызова tail
, этот вызов будет хвостовым рекурсивным (с CLR 4, но все же есть некоторые исключения, где он не будет фактически хвостом рекурсивным). Но это не обязательно означает, что вся функция является хвостовой рекурсивной. Например, я могу представить, что функция QuickSort скомпилирована так, что первый рекурсивный вызов не является хвостовым рекурсивным, а второй -.
Кроме того, только потому, что некоторая функция не содержит инструкции tail
, это не обязательно означает, что она не является хвостовой рекурсивной. Компилятор JIT может распознать хвостовой вызов даже без инструкции tail
и оптимизировать его как таковой.
Более того, компилятор F # иногда компилирует рекурсивные функции нерекурсивным способом. Это несколько отличается от обычной оптимизации хвостового вызова, и инструкция tail
не используется, но общий эффект аналогичен.
В некоторых случаях компилятор F # преобразует некоторые рекурсивные случаи в нечто, что напоминает 'goto', не используя инструкцию' .tail' - обнаружить это может быть сложно –
Зачем вам это нужно? – Brian
@Brain: Вы спрашиваете, хочу ли я знать, когда функция хвоста рекурсивна? Если это так, это должно помочь мне написать более эффективный код. Это было бы похоже на мгновенную обратную связь, если бы я сделал то, что было оптимизировано как хвостовое рекурсивно, а затем с одним неправильным изменением не сделало его хвостом рекурсивным. Подумайте об этом так. У вас есть код в производстве, который является хвостом рекурсивным, вы вносите небольшое изменение, и теперь оно не является хвостом рекурсивным. Он идет в производство, и внезапно начинается переполнение стека. Вы никогда не видели, как это происходит. –