This question already has an answer here:

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

(* 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:

(* DoSomethingElseBefore[tag,8,44] *)

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


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



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[_]=_?


marked as duplicate by Mr.Wizard Jan 25 '14 at 10:02

This question has been asked before and already has an answer. If those answers do not fully address your question, please ask a new question.

  • 1
    $\begingroup$ 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. $\endgroup$ – Andrew Cheong Jan 25 '14 at 3:25
  • $\begingroup$ You should check the function UpValues $\endgroup$ – Rojo Jan 25 '14 at 7:24
  • $\begingroup$ Related: (27165), (39711) $\endgroup$ – Mr.Wizard Jan 25 '14 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

To answer your second question:

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

(* {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] = ...


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}];
  ] /; Not[TrueQ[didBefore]]

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