12
$\begingroup$

As we know we can assign special addition rules to symbols by using UpValues:

ClearAll[mySymbol]
mySymbol /: mySymbol + x_ := {mySymbol, x}

They are used when we directly add something to mySymbol

mySymbol + 5
(* {mySymbol, 5} *)
mySymbol + mySymbol
(* {mySymbol, mySymbol} *)

but also when we use some other functions as += (AddTo):

ClearAll[tmp]
tmp = mySymbol;
tmp += 5
(* {mySymbol, 5} *)
tmp
(* {mySymbol, 5} *)

In Mathematica versions 8 and 9 it also worked when we added expression to itself:

$Version
(* "9.0 for Linux x86 (64-bit) (February 7, 2013)" *)
ClearAll[tmp]
tmp = mySymbol;
tmp += mySymbol
(* {mySymbol, mySymbol} *)
tmp
(* {mySymbol, mySymbol} *)

In versions 10.0, 10.1 and 10.2 it doesn't work like that anymore and AddTo, when adding same expressions, always returns 2 times expression even if Plus was overridden.

$Version
(* "10.0 for Linux x86 (64-bit) (December 4, 2014)" *)
ClearAll[tmp]
tmp = mySymbol;
tmp += mySymbol
(* 2 mySymbol *)
tmp
(* 2 mySymbol *)

Is this a bug, or should we not rely on overridden Plus when using functions like AddTo and override them separately?


Edit

It seems some built-ins, like Interval, relied on this and are broken in v10:

$Version
(* "10.0 for Linux x86 (64-bit) (December 4, 2014)" *)
ClearAll[tmp]
tmp = Interval[{0, 1}, {4, 5}];
tmp + tmp
(* Interval[{0, 2}, {4, 6}, {8, 10}] *)
tmp += tmp
(* Interval[{0, 2}, {8, 10}] *)
$\endgroup$
  • 6
    $\begingroup$ I'd say the latter, because relying on AddTo picking up Plus overloading is relying on implementation details, namely that AddTwo uses Plus behind the scene. This may be so (as it was before), or may be not (as it apparently is now), but one can't really rely on this relation. $\endgroup$ – Leonid Shifrin Sep 9 '15 at 14:24
  • $\begingroup$ @Leonid While I don't disagree regarding user defined functions. There seems to be a bug related to this in Interval implementation. $\endgroup$ – jkuczm Sep 9 '15 at 14:35
  • 2
    $\begingroup$ As @Leonid says, before version 10, AddTo used the top-level equivalents of Set and Plus, thus calling the evaluator, which caused serious inefficiencies. They have now been corrected. $\endgroup$ – ilian Sep 9 '15 at 14:35
  • $\begingroup$ Well, then ask a question about that bug :) Oh, I see you did. $\endgroup$ – Leonid Shifrin Sep 9 '15 at 14:39
  • 4
    $\begingroup$ Yes, I think the Interval example is a bug and filed a report. Thank you for pointing it out. $\endgroup$ – ilian Sep 9 '15 at 14:48
6
$\begingroup$

You can use Hold to simulate the behavior you originally had

$Version

(* "10.2.0 for Mac OS X x86 (64-bit) (July 7, 2015)" *)

ClearAll[mySymbol]
mySymbol /: mySymbol + x_ := {mySymbol, x}
mySymbol /: mySymbol + Hold[x_] := {mySymbol, x}

tmp = mySymbol;
tmp += 5

(* {mySymbol, 5} *)

tmp = mySymbol;
tmp += Hold[mySymbol]

(* {mySymbol, mySymbol} *)
$\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.