I think that your mechanism is reasonably robust for common use cases, but not fully robust if one wants to take into account all possible ways that the value (or, generally, global properties) of the symbol can be changed in Mathematica.
My current opinion is that making such triggering mechanism fully robust without new system support is very hard or may not be possible at all. Such system support may exist but just not be known to me, however. One place to look at are functions
Internal`AddHandler["VetoableValueChange", myVetoFunction]. I do know how to make them work with
DownValues, but not with
Note that, to make your current mechanism more robust, you will have to add similar definitions not just to
SetDelayed, but also to
TagSetDelayed. The interesting thing about them is that while the definitions they create may end up being exactly the same as if you used
SetDelayed, they use independent assignment mechanism, so assignment like
$var /: $var = 1
won't trigger your mechanism.
One way to more or less systematically analyze this issue is to look at all built-in functions with
Hold* attributes. For functions in the
System` context, one can use something like
ToExpression[#, StandardForm, Attributes],
HoldAll | HoldFirst | HoldRest | HoldAllComplete
I have manually selected a number of functions from this list which affect, directly or indirectly, some of the global properties of the symbol in question. These functions can be divided into several groups according to their actions. Let us list cases where your mechanism does and does not work, based on such division:
Direct assignment operators:
TagSetDelayed (and possibly also
UpSetDelayed, depending on whether or not you want to account for changes they can introduce). Here also belong
These functions you can account for explicitly, using definitions similar to what you posted.
In-place modification operators, such as
Luckily, these are implemented using some of the more fundamental assignment operators, so they are all triggered via your method.
Operators which clear or remove symbols:
Context. Whether to include or exclude these is a matter of choice, but all of them are not triggered by your mechanism, but you could add more rules to cover these ones too, in analogy with
Set. I added
Context here, because you can change the context of your variable via
Context[$var] = "NewContext`"
and this effectively removes the variable from its current context.
Functions providing lower-level access to symbol's properties:
UpValues. Again, depending on how general you want to be, you can include only some of them, but at least you will have to include
Direct assignments involving these functions will not trigger your mechanism, e.g.:
OwnValues[$var] = HoldPattern[$var] :> 10
and covering these cases does not seem possible using the
Functions such as
Language`ExtendedFullDefinition can be assigned to (as you have enlightened us yourself here), for example as
var1 = 10;
Language`ExtendedFullDefinition[var1] /. HoldPattern[var1] :> $var
and such assignments will not be triggered by your method. Again,
UpValues won't probably help here.
Block: it blocks all definitions attached to a symbol, so if the symbol is
Block-ed, assignments inside
Block will not be triggered.
Part assignments: these will not be triggered either. For example:
$var = Range;
$var[] = 100
This one also seems beyond the reach of the
UpValues- based method.
I am fairly sure that I missed some more possibilities of value changes for symbols. Some functions in
Language` and possibly some other contexts may introduce yet more ways to change the values.
I think that what you've got can be made good enough with a modest amount of additional rules, and will cover many or most common use cases. However, making this fully robust requires dedicated system support. It may be that such API already exists somehere in one of the contexts I mentioned earlier, but is just not known to me. As I mentioned already,
Internal`AddHandler["VetoableValueChange",...] may be the right ones to look at, but I don't fully know how they work.