# Is it possible to define custom compound assignment operators like ⊕= similar to built-ins +=, *= etc?

I would like to do something like this:

In[1]:= ToExpression["\"\\[CirclePlus]\""]
Out[1]= ⊕

In[2]:= list_ ⊕ element_ := Append[list, element];

In[3]:= a = {1, 2};

In[4]:= {a = a ⊕ 3, a}
Out[4]= {{1, 2, 3}, {1, 2, 3}}

In[5]:= {a ⊕= 4, a}

(* Desired result: Out[5]= {{1, 2, 3, 4}, {1, 2, 3, 4}} *)
(* Actual result: syntax error *)

Syntax::sntxf: "a⊕" cannot be followed by "=4".


Is it possible to workaround this error and make the compound assignment operator ⊕= work?

-
Infact CirclePlus[x_List, y_] := Append[x, y] works. Then you can try things like "{1,2,3} \ [CirclePlus] 4". –  Ali Jun 16 '13 at 5:13
I tried something along these lines: reference.wolfram.com/mathematica/tutorial/…, but failed. –  Vladimir Reshetnikov Jun 16 '13 at 5:51
Unfortunately, you cannot define new operators like this. You can have the operator itself, but not the sigil to represent it, as it seems that the parser is not user-programmable. If it were, the Notation package wouldn't be needed. –  Oleksandr R. Jun 16 '13 at 6:16
You can have it if you can live with using an input alias (esc + sth + esc) to input it. If you build your operator from other operators with sub-super-under-etcscripts, then it is more straighforward. Are you interested in any of these solutions? –  Rojo Jun 16 '13 at 18:46
I would add one caution: \[CirclePlus], etc. are System  symbols, and while they do not have any defined behavior (which makes them nice to overload), adding a definition will seemingly "break" the encapsulation of unique notebook or cell group contexts. The key is they're essentially global, so if you define them in one place, the definition is accessible without any qualifications. Yes, I've done this to myself. –  rcollyer Jun 18 '13 at 15:49

This is my little test, and I encountered with some problems.

 (*Input 1 ==< *)
(list_) \[CirclePlus] (element_) := Append[list, element];

(*Input 2 ==< *)
(x_List) \[CirclePlus] (y_) := Append[x, y]


Failed try.

 (*Input 3 ==< *)

(*Input 4 ==< *)

(*
Output==>
AppendTo[{1,2,3},6]
*)

 (*Input 5 ==< *)
a = {1, 2, 3, 4};


Use one new variable name z

 (*Input 6 ==< *)

(*Input 7 ==< *)
CircleAddTo[x_List, y_] := (Clear[z]; z = Append[x, y])

(*Input 8 ==< *)

(*
Output==>
{{1,2,3,4,10},{1,2,3,4}}
*)

 (*Input 9 ==< *)

(*
Output==>
{{1,2,3,4,10},{1,2,3,4,10}}
*)


one method use string symbol

Convert CircleAddTo to string symbol $\text{$\oplus $=}$

 (*Input 10 ==< *)

(*Input 11 ==< *)
{a~"\[CirclePlus]="~7,z,a}

(*
Output==>
{{1,2,3,4,7},{1,2,3,4,7},{1,2,3,4}}
*)


Of couse,we could use one New Sybmol to replace the compound symbol $\oplus =$

 (*Input 12 ==< *)
(a_) \[CircleTimes] (b_) := CircleAddTo[a, b]

(*Input 13 ==< *)
a \[CircleTimes] 9

(*
Output==>
{1,2,3,4,9}
*)

 (*Input 14 ==< *)
{z, a}

(*
Output==>
{{1,2,3,4,9},{1,2,3,4}}
*)


or

 (*Input 15 ==< *)

(*Input 16 ==< *)
{a~p~7, z, a}

(*
Output==>
{{1,2,3,4,7},{1,2,3,4,7},{1,2,3,4}}
*)


# NotationPackage

Notation/tutorial/NotationSymbolizeAndInfixNotation

 (*Input 17 ==< *)
<< "Notation"

(*Input 18 ==< *)
Cell[BoxData[RowBox[{"InfixNotation", "[", RowBox[{TemplateBox[{SubscriptBox["\[CirclePlus]", "="]},"NotationTemplateTag"], ",","CircleAddTo"}], "]"}]], "Input"]


 (*Input 19 ==< *)

(*
Output==>
{1,2,3,4,6}
*)

-

Best option in my view is to use a compound operator based on an already defined operator, whose precedence is inherited, with the Notation package or by redefining MakeExpression.

MakeExpression[
RowBox[{b___, x_, UnderscriptBox["=", "\[CirclePlus]"], y_, a___}],
StandardForm] :=
MakeExpression[
RowBox[{b, RowBox[{"gplus", "[", RowBox[{x, ",", y}], "]"}], a}],
StandardForm]


This underscript is probably quite weird but you can do as you wish (probably an overscript made more sense). As it is, your operator is an equal sign with an underscripted circle plus. However, some boxes are transparent for parsing, so you could define the following input alias for a different layout of the operator

PrependTo[CurrentValue[InputNotebook[], InputAliases],
"c+=" -> FrameBox[UnderscriptBox["=",
BoxBaselineShift -> -2.5,
BoxMargins -> {{-0.7638888888888887,
0.7638888888888887}, {2.5, -2.5}}]],
BoxFrame -> False, FrameMargins -> {{5, 0}, {0, 0}}]]


There's also the option to redefine MakeExpression` directly on a TagBox of a RowBox, or to use some box in which the lhs and the rhs of the operation are parts of it (this is probably the simplest way), but I'd stay with the first option.

-