Формулируя ответ на другой вопрос SO , я обнаружил странное поведение, касающееся хвостовой рекурсии в Mathematica.
Документация Mathematica намекает, что может быть выполнена оптимизация хвостовых вызовов . Но мои собственные эксперименты дают противоречивые результаты. Сравните, например, следующие два выражения. Первое вызывает сбой ядра 7.0.1, предположительно из-за исчерпания стека:
(* warning: crashes the kernel! *)
Module[{f, n = 0},
f[x_] := (n += 1; f[x + 1]);
TimeConstrained[Block[{$RecursionLimit = Infinity}, f[0]], 300, n]
]
Второй запускается до завершения, по-видимому, для использования оптимизации хвостового вызова для возврата значимого результата:
Module[{f, n = 0},
f[x_] := Null /; (n += 1; False);
f[x_] := f[x + 1];
TimeConstrained[Block[{$IterationLimit = Infinity}, f[0]], 300, n]
]
Оба выражения определяют хвостовую рекурсивную функцию f
. В случае первой функции Mathematica, по-видимому, считает наличие составного оператора достаточным, чтобы исключить любую возможность оптимизации хвостового вызова. Также обратите внимание, что первое выражение управляется $ RecursionLimit
, а второе - $ IterationLimit
- это признак того, что Mathematica по-разному обрабатывает эти два выражения. (Примечание: упомянутый выше SO-ответ имеет менее надуманную функцию, которая успешно использует оптимизацию хвостового вызова.)
Итак, вопрос : знает ли кто-нибудь обстоятельства, при которых Mathematica выполняет оптимизацию хвостового вызова рекурсивных функций? Ссылка на окончательное утверждение в документации Mathematica или другом материале WRI была бы идеальной. Спекуляции также приветствуются.