8
$\begingroup$

For some reason,

$Assumptions := (Print["y"]; x > 0)

evaluates the RHS immediately.

I have code in which $Assumptions dynamically changes, and where the RHS is complicated for general cases and takes a long time to evaluate. So I need to delay its evaluation until it is needed. What can I do to delay evaluation?

$\endgroup$
1
  • 2
    $\begingroup$ I noticed too that $Assumptions is special. The values you set are checked immediately. Try e.g. $Assumptions =. and you'll see that after this it is still set to True. Try $Assumptions = {False}, and notice the warning message "Warning: one or more assumptions evaluated to False." $\endgroup$
    – Szabolcs
    Commented May 13, 2016 at 9:59

2 Answers 2

5
$\begingroup$

As I somehow forgot but Szabolcs reminded me many System variables (typically with names beginning with $) check the values they are set to, e.g.:

$MinPrecision := -6

$MinPrecision

\$MinPrecision::precset: Cannot set \$MinPrecision to -6; value must be a non-negative number or Infinity. >>

0

In this case the check causes evaluation you do not want. You can bypass it by modifying the OwnValues directly. A helper function to make this cleaner:

SetAttributes[mySet, HoldAll]
mySet[LHS_Symbol, RHS_] := (OwnValues[LHS] = {HoldPattern[LHS] :> RHS};)

Now:

mySet[$Assumptions, Print["y"]; x > 0]  (* nothing prints *)

and:

Refine[{x < 0, x == 0, x > 0}]

y

{False, False, True}

Also:

mySet[$Assumptions, Print["y = ", y]; x > y]

y = 1;
Refine[{x > 1, x > 2, x > 3}]

y = 2;
Refine[{x > 1, x > 2, x > 3}]

y = 3;
Refine[{x > 1, x > 2, x > 3}]

y = 1

{True, x > 2, x > 3}

y = 2

{True, True, x > 3}

y = 3

{True, True, True}
$\endgroup$
4
  • 1
    $\begingroup$ "I don't yet understand why your assignment triggers additional evaluation of the RHS" <- Try x=-1; $Assumptions := {x>0}. I think this explains why. $\endgroup$
    – Szabolcs
    Commented May 13, 2016 at 10:00
  • $\begingroup$ @Szabolcs Ah, I completely forgot about those checks; thanks. I see that you did not vote for this answer; do you consider it dangerous? $\endgroup$
    – Mr.Wizard
    Commented May 13, 2016 at 10:29
  • $\begingroup$ I forget about voting sometimes. But I thought moderators cannot see who voted and who didn't. About the dangers: I don't know. It works, but I won't be very surprised if something strange happens. But it probably won't. You should get some sleep BTW. Isn't it 4 am there? $\endgroup$
    – Szabolcs
    Commented May 13, 2016 at 11:06
  • 1
    $\begingroup$ @Szabolcs There were zero votes of any kind at the time of my comment; it did not require a vast leap of deduction to conclude that you had not voted on it. ;-) $\endgroup$
    – Mr.Wizard
    Commented May 13, 2016 at 11:12
4
$\begingroup$

To change the assumptions dynamically, this can be used:

$Assumptions := b
b = {c > 0};
Refine[{c < 0, c == 0, c > 0}]

b = {c < 0};
Refine[{c < 0, c == 0, c > 0}]

If you need to evaluate the Print every time, this can be used:

$Assumptions := Evaluate[b]
b = {c > 0, Unevaluated@Print[kount]};
kount = 1;
Refine[{c < 0, c == 0, c > 0}]
kount = 2;
Refine[{c < 0, c == 0, c > 0}]

b = {c < 0, Unevaluated@Print[kount]};
kount = 3;
Refine[{c < 0, c == 0, c > 0}]
kount = 4;
Refine[{c < 0, c == 0, c > 0}]

Beware, however, that using Print in the assumptions could have unintended consequences. Print returns Null, so the effect will be that Null will be assumed to be True, as illustrated here:

$Assumptions = {Print["beware"]};
Refine[Null]

(* beware *)

(* True *)
$\endgroup$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

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