Окончательный вопрос о рекурсии - PullRequest
3 голосов
/ 19 февраля 2010

После участия в дискуссии по этому фиаско вопросу я хотел бы поставить вопрос перед всем сообществом.

В каких случаях будет применяться оптимизация при помощи хвостового вызова к коду на основе .Net?

Пожалуйста, поддержите ваши ответы надежными, современными источниками или воспроизводимыми экспериментами.

1 Ответ

4 голосов
/ 19 февраля 2010

Согласно «Эксперту F #», написанному Доном Саймом и др., F # выполняет оптимизацию хвостового вызова. Кажется, я помню, как читал в блоге Эрика Липперта, что компилятор C # (любой версии) этого не делает. Поправь меня, если я ошибаюсь, Эрик. Во всех случаях можно выполнить оптимизацию хвостового вызова, когда последняя инструкция должна вызвать метод. Часто это будет рекурсивный вызов самого метода, но это не обязательно. Оптимизация может быть выполнена, поскольку гарантируется, что текущий кадр стека больше не нужен. Однако если впоследствии необходимо выполнить простую операцию, оптимизация не может быть выполнена.

int Fib(int n)
{
  if(n < 2)
     return 1;

  return Fib(n-1) + Fib(n-2);
}

Это не может быть оптимизировано хвостовым вызовом, потому что + не может быть оценено до того, как последний вызов Fib вернется. (На самом деле я думаю, что этот пример также используется в Expert F #, но не уверен в этом.)

int Fib(int n, int a, int b)
{
  if(n == 0)
    return a+b;
  return Fib(n-1,a+b,a);
}

Эта версия может быть оптимизирована с помощью хвостового вызова, поскольку все аргументы оцениваются перед последним вызовом Fib и никаких операций после вызова не существует, поэтому текущий кадр стека можно отбросить.

...