2012-03-14 1 views
4

Так как .net имеет код операции TailCall, это можно использовать для дефиниции, если функция F # действительно является хвостовой рекурсивной?Может ли функция F # считаться хвостовой рекурсивной, она использует код операции TETCALL .net

Если это правда, кто-нибудь сделал надстройку VS, которая идентифицирует функции хвоста и не хвоста?

+0

В некоторых случаях компилятор F # преобразует некоторые рекурсивные случаи в нечто, что напоминает 'goto', не используя инструкцию' .tail' - обнаружить это может быть сложно –

+0

Зачем вам это нужно? – Brian

+1

@Brain: Вы спрашиваете, хочу ли я знать, когда функция хвоста рекурсивна? Если это так, это должно помочь мне написать более эффективный код. Это было бы похоже на мгновенную обратную связь, если бы я сделал то, что было оптимизировано как хвостовое рекурсивно, а затем с одним неправильным изменением не сделало его хвостом рекурсивным. Подумайте об этом так. У вас есть код в производстве, который является хвостом рекурсивным, вы вносите небольшое изменение, и теперь оно не является хвостом рекурсивным. Он идет в производство, и внезапно начинается переполнение стека. Вы никогда не видели, как это происходит. –

ответ

6

См. this blog post в блоге команды F # для краткого изложения того, как F # компилирует хвостовые вызовы.

Короче говоря,

  1. Прямые рекурсивные вызовы хвост, как правило, преобразуются в петли.
  2. Взаимные рекурсивные и косвенные нерекурсивные хвостовые вызовы обычно превращаются в хвостовые вызовы .NET.

но смотри полную запись обо всех деталях gory.

+0

Хороший ответ, прочитайте сообщение. В конце он говорит: «Я надеюсь, что эта информация была полезной. Моя следующая публикация расскажет о способах преодоления некоторых ограничений, охватываемых этим сообщением». любая идея о том, где следующий пост? –

+1

@GuyCoder - хороший вопрос. Он попал на задний план, когда мы начали делать больше работы с поставщиком, но я постараюсь закончить его. – kvb

+0

Можете ли вы рассказать об этом в своем следующем посте? http://blogs.msdn.com/b/jomo_fisher/archive/2007/09/24/adventures-in-f-corecursion.aspx –

3

Да, если компилятор испускает команду вызова tail, этот вызов будет хвостовым рекурсивным (с CLR 4, но все же есть некоторые исключения, где он не будет фактически хвостом рекурсивным). Но это не обязательно означает, что вся функция является хвостовой рекурсивной. Например, я могу представить, что функция QuickSort скомпилирована так, что первый рекурсивный вызов не является хвостовым рекурсивным, а второй -.

Кроме того, только потому, что некоторая функция не содержит инструкции tail, это не обязательно означает, что она не является хвостовой рекурсивной. Компилятор JIT может распознать хвостовой вызов даже без инструкции tail и оптимизировать его как таковой.

Более того, компилятор F # иногда компилирует рекурсивные функции нерекурсивным способом. Это несколько отличается от обычной оптимизации хвостового вызова, и инструкция tail не используется, но общий эффект аналогичен.

Смежные вопросы