Skip to main content
Fixed title
Link
jjc385
  • 3.5k
  • 1
  • 18
  • 29

How is LHS = RHS; ... ; RHSLHS (nontrivially) different from ... ; RHS

Tweeted twitter.com/#!/StackMma/status/587809487425245185
Corrected result in 3rd example (Thanks, Kuba!)
Source Link
jjc385
  • 3.5k
  • 1
  • 18
  • 29
(* Third example *)
ClearAll[LHS, f, F, changeQ];

changeQ[x_] := False
LHS = f[x];

f[x_?changeQ] := F[x]
changeQ[x] := True
LHS
(* f[x]F[x] *)
(* Third example *)
ClearAll[LHS, f, F, changeQ];

changeQ[x_] := False
LHS = f[x];

f[x_?changeQ] := F[x]
changeQ[x] := True
LHS
(* f[x] *)
(* Third example *)
ClearAll[LHS, f, F, changeQ];

changeQ[x_] := False
LHS = f[x];

f[x_?changeQ] := F[x]
changeQ[x] := True
LHS
(* F[x] *)
Source Link
jjc385
  • 3.5k
  • 1
  • 18
  • 29

How is LHS = RHS; ... ; RHS (nontrivially) different from ... ; RHS

I'm trying to understand how Mathematica thinks about the results of Set. Suppose we perform LHS = RHS. I'm focusing on when Mathematica considers LHS to be fully evaluated and when it decides to evaluate LHS again later.

Discussion and Examples

Suppose I do the following:

(* First example *)
ClearAll[ LHS, f, F ];
LHS = f[x];  (* f[x] *)
f[x_] := F[x]
LHS
(* F[x] *)

This is what I would have expected to happen -- LHS is re-evaluated at the end.

Now, the following works a bit differently:

(* Second example *)
ClearAll[LHS, f, F, changeQ];

changeQ[x_] := False
f[x_?changeQ] := F[x]

LHS = f[x];
changeQ[x] := True
LHS
(* f[x] *)

Apparently Mathematica decided not to re-evaluate LHS at the end, otherwise it would evaluate to F[x]. This is a case where LHS and f[x] evaluate to different quantities.

Interestingly enough, swapping the order of two lines in the above changes the outcome:

(* Third example *)
ClearAll[LHS, f, F, changeQ];

changeQ[x_] := False
LHS = f[x];

f[x_?changeQ] := F[x]
changeQ[x] := True
LHS
(* f[x] *)

Swapping the order made LHS re-evaluate at the end, just like in the first example.

This leads me to more formally pose and tentatively answer the question:

Question

Suppose, for some choice of initialCode and additionalCode, we perform

initialCode
LHS = f[x];  (* f[x] *)
additionalCode
LHS

Assuming that LHS originally evaluated to f[x],

  1. For what types of additionalCode (and possibly initialCode) does the final evaluation of LHS yield something different from evaluating f[x]?

  2. If LHS and f[x] evaluate to different values (as is the case at the end of the second example above), is it possible to somehow "force" LHS to evaluate in the same way as f[x]?

Tentative Answer to Question 1

(Based on evidence from above examples)

  • LHS will re-evaluate when additionalCode gives a down value to f (See 1st and 3rd examples above)
  • LHS will not re-evaluate in general. (See 2nd example above, where a down value was given to a different function, changedQ.)

Follow Up

Assuming the tentative answer is along the right track, I'm looking for two things:

  • How does Mathematica 'know' when to re-evaluate LHS? I'm particularly interested in the vocabulary used to describe the process.
  • Are there any other conditions under which LHS re-evaluates?
  • Is there a generic way to force LHS to re-evaluate? (This is similar to the second question above.)

Of course, I'd welcome any suggestions for good references on this.