# How do I extend (prepend or append to) an existing TagSetDelayed rule? [duplicate]

I have a TagSetDelayed rule associated with, say, tag:

tag/:(tag[key_]=val_):=DoSomething[tag,key,val]
tag[7]=43
(* DoSomething[tag,7,43] *)


I want to modify that rule to do something before what it already does, preserving what it already does. Of course, the following only overrides the existing rule:

tag/:(tag[key_]=val_):=DoSomethingElseBefore[tag,key,val]
tag[8]=44
(* DoSomethingElseBefore[tag,8,44] *)


I'd like, instead, to end up with the result of this:

tag/:(tag[key_]=val_):=(
DoSomethingElseBefore[tag,key,val];
DoSomething[tag,key,val];
);


I'm not sure how to "introspect", i.e. "paste" the existing rule as I redefine the rule, like so:

tag/:(tag[key_]=val_):=(
DoSomethingElseBefore[tag,key,val];
ExistingTagSetDelayedRule[]
);


Edit

I realized I could use ?tag to see a list of associated rules, but how would I extract the RHS of the appropriate form, tag[_]=_?

?tag
Globaltag
(tag[key_]=val_)^:=DoSomething[tag,key,val]

-

## marked as duplicate by Mr.Wizard♦Jan 25 at 10:02

Coming from a C++/Tcl background I may be using wrong / ambiguous / confusing terms—please do point such out and help me improve my question. –  Andrew Cheong Jan 25 at 3:25
You should check the function UpValues –  Rojo Jan 25 at 7:24
Related: (27165), (39711) –  Mr.Wizard Jan 25 at 10:02

One easy method is to use the following construct

tag /: (tag[key_] = val_) := Block[{didBefore = True},
Print[{tag, key, val}];
tag[key] = val
] /; Not[TrueQ[didBefore]]


and you get

tag[7] = 43

(* {tag,7,43} *)
(* DoSomething[tag, 7, 43] *)


Here, the Print was injected before your actual call. If you are puzzled now, this is OK, because the approach is not obvious. For more information please look in the comments here or read here

how would I extract the RHS of the appropriate form, tag[]=?

First you have to know which kind of rule is used. In your case you assigned it to the UpValues of tag

UpValues[tag]
(* {HoldPattern[tag[key_] = val_] :> DoSomething[tag, key, val]} *)


and of course you could (but probably shouldn't) assign these rules directly by using

UpValues[tag] = ...


### Sidenote

If you have understand the first approach, then you can write it a bit shorter, without repeating the = call, because this could in reality be more complex

tag /: code : (tag[key_] = val_) := Block[{didBefore = True},
Print[{tag, key, val}];
code
] /; Not[TrueQ[didBefore]]
`
-