Пытаясь u[x_] := x; Trace[x*u[x] /. x -> 2]
, сначала оцениваются x
и u[x]
. Тогда в вашем случае он сначала пытается оценить fact[x-1]
, прежде чем заменить x
на 2, и достигает предела рекурсии.
Attributes[ReplaceAll]
показывает, что у него нет атрибута HoldFirst
, поэтому он начинает с оценки своего первого аргумента. Например,
ReleaseHold@ReplaceAll[Hold[x*fact[x - 1]], x -> 2]
дает ожидаемое 2
, поскольку содержит первый аргумент, заменяет, а затем освобождает удержание, как вы и предполагали.
Еще один способ сделать это -
Unprotect[ReplaceAll]
SetAttributes[ReplaceAll, HoldFirst]
ReplaceAll[x*fact[x - 1], x -> 2]
но не делай этого.
Конечно, кто-то скоро даст лучшее объяснение.
РЕДАКТИРОВАТЬ: В ответ на добавленный вопрос о том, почему
Clear[factif]
factif[n_] := If[n < 1, 1, n factif[n - 1]]
не приводит к бесконечной рекурсии: при таком определении factif[x]
оценивается как If[x < 1, 1, x factif[x - 1]]
, поскольку x<1
не может быть оценено. Таким образом, он остается в этой форме после попытки вычисления первого аргумента ReplaceAll
, затем происходит замена и т. Д.