Согласно «Эксперту 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 и никаких операций после вызова не существует, поэтому текущий кадр стека можно отбросить.