15

Exploring another problem and this example of @halirutan, I came across an evaluation behavior I don't understand.

When g[] below is evaluated the first time, ig[] is evaluated and a message printed; on subsequent calls to g[], ig[] is not evaluated. This can be verified with Trace.

ClearAll[g, ig];
g::msg = "Message";
ig[] := Module[{}, Null /; (Message[g::msg]; False)];
g[] := Module[{res = ig[]}, res /; FreeQ[res, ig]];

It is as if Mathematica decided that ig[] is constant and assumes it does not need to be called further. However, each time ig[] is executed in the front end directly, it is evaluated, a message is printed, and it returns ig[].

With the modification below, in which ih[] is not constant, the first four times h[] is evaluated the function ih[] is evaluated. In subsequent evaluations of h[], ih[] is not evaluated again.

ClearAll[h, ih];
h::msg = "Message";
n = 2^4;
ih[] := Module[{}, n /; (n /= 2; Message[h::msg]; EvenQ[n])];
h[] := Module[{res = ih[]}, res /; FreeQ[res, ih]];

That is, once n becomes odd and EvenQ[n] tests False, the evaluation of h[] seems to change so that ih[] is no longer called from within h[].

Is this right, or am I missing something? Is this how it should be?

Michael E2
  • 235,386
  • 17
  • 334
  • 747

1 Answers1

19

You need to use Update, e.g. Update[ig] or Update[ih], to tell Mathematica that the condition has changed and it should reevaluate ig or ih.

Also, see (1765) and (79486).

Carl Woll
  • 130,679
  • 6
  • 243
  • 355