9
$\begingroup$

Consider a function that sorts its arguments based on a function called order

Clear[f, order]
f[x_, y_] /; order[x] > order[y] := f[y, x]
order[1] = 1;
order[2] = 2;
expr1 = f[1, 2]
expr2 = f[2, 1]
(* f[1, 2] *)
(* f[1, 2] *)

However, let's imagine that we change the ordering function

order[1] = 2;
order[2] = 1;

Surprisingly, expr1 and expr2 still evaluate to f[1,2]

expr1
expr2
(* f[1, 2] *)
(* f[1, 2] *)

However, if we introduce f[1, 2] we obtain the correct result

f[1, 2]
(* f[2, 1] *)

Is there a way to force the reevaluation of expr to obtain f[2, 1]? I am looking for a function along the lines of

ForceEvaluation@expr1
ForceEvaluation@expr2
(* f[2, 1] *)
(* f[2, 1] *)
$\endgroup$
  • 1
    $\begingroup$ While I appreciate the accept, I'd recommend holding off for at least a few more hours. There are plenty of users who know more about Mathematica than I who might be able to provide a better answer, but once an answer is accepted many people will start skipping the question entirely. $\endgroup$ – eyorble Dec 19 '18 at 18:12
  • $\begingroup$ Thanks for the comment, since I am new I did not consider this. It is certainly an obscure behaviour of Mathematica, and it would be great to hear more about it! $\endgroup$ – AGim Dec 19 '18 at 18:17
  • 1
    $\begingroup$ Related, but not as minimal an example: (139461) $\endgroup$ – Mr.Wizard Dec 19 '18 at 21:26
11
$\begingroup$

Stumbled across the solution to this in tutorial/ControllingInfiniteEvaluation in the documentation. The last paragraph says:

Some of the trickiest cases occur when you have rules that depend on complicated /; conditions (see "Putting Constraints on Patterns"). One particularly awkward case is when the condition involves a "global variable". The Wolfram Language may think that the evaluation is finished because the expression did not change. However, a side effect of some other operation could change the value of the global variable, and so should lead to a new result in the evaluation. The best way to avoid this kind of difficulty is not to use global variables in /; conditions. If all else fails, you can type Update[s] to tell the Wolfram Language to update all expressions involving s. Update[] tells the Wolfram Language to update absolutely all expressions.

The symbol to updated in this case is f, rather than order, but:

Clear[f, order]
f[x_, y_] /; order[x] > order[y] := f[y, x]
order[1] = 1;
order[2] = 2;
expr1 = f[1, 2];
expr2 = f[2, 1];
{expr1, expr2}

{f[1, 2], f[1, 2]}

order[1] = 2;
order[2] = 1;
Update[f];
{expr1, expr2}

{f[2, 1], f[2, 1]}

Clunky, but it works.

$\endgroup$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.