Оптимизация хвостового вызова в Mathematica?

Формулируя ответ на другой вопрос 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 была бы идеальной. Спекуляции также приветствуются.

28
задан Community 23 May 2017 в 11:54
поделиться