So, I had a look at that old version of my notebook and I found it too specific. I copy here part of what was the documentation of my Override.m package. It's more general. (I'll spare you the code required to add options...)
Here we go.
It's easy to redefine a built-in procedure so that it can call itself without incurring in an infinite recursion. The key idea is to condition the new definition by means of variable, say $override, that prevents built-in evaluation and diverts the call to user defined code. If this code needs to call the built-in version of the procedure, all it has to do is to change the value of the variable $override so that it won't call itself. In a way the use of this variable is analogous to specifying the prefix 'super' that is used in Java programming to refer to a method of a superclass from within an overriding method with the same signature.
Here, the value of $override is initialized to True in order to prevent Mathematica from taking over the user defined code. Protecting the variable is a good idea.
$override = True;
Protect[$override];
Now, whenever we want to redefine a built-in procedure, let's call it BuiltinProc, in term of itself we just define it with a conditioned left hand side (so that the definition applies only when $override = True) and enclose the portion of code that calls the original procedure in a Block that sets $override = False. Better yet we can call, from inside the Block, our own code that can make use of the built-in procedure as we would in a fresh Mathematica kernel. Let's call userProc the user defined code:
Unprotect[BuiltinProc];
BuiltinProc[argsandopts___ ] /; $override == True :=
Block[
{$override = False},
userProc[argsandopts]
];
Protect[BuiltinProc];
(Unprotecting and Protecting are needed since the built-in symbols are by default protected). Note that when the argument sequence argsandopts is the same as for the built-in procedure (as is the case with such a general pattern matching scheme) we are in fact redefining it.
Once we've done this, we can write the code for userProc and allow it to call the built-in procedure at will: since it's called inside a Block that sets $override=False we do not need to worry about the value of $override inside the code. Calling BuiltinProc in the global environment (where $override is True) will result in a call to userProc and in a (possible) call to BuiltinProc inside a Block where $override is False. There is no danger to incur in an infinite recursion since the two calls to BuiltinProc are in fact different and complementary.
This is a sample code that adds to the previous snippets and shows that whenever userProc is called it will use the built-in procedure whose arguments and options have been suitably processed before being passed to it:
userProc[args___, opts___Rule] :=
(
Print["This code was called from a Block
that temporarily set $override to ", $override, ". \nThe following \
function contains a call to the original BuiltinProc without conditions." ];
oldargs = FA[args]; oldopts = FO[opts];
myFun[
BuiltinProc[oldargs, oldopts],
otherargsandopts
]
)
When we call BuiltinProc in a global environment where $override=True we are in fact calling userProc that, in turn, can use the built-in code of the original built-in procedure:
BuiltinProc[x, y, {a, b}, myopt -> Automatic]
This code was called from a Block that temporarily set $override to False.
The following function contains a call to the original BuiltinProc without
conditions.
myFun(BuiltinProc(FA(x, y, {a, b}), FO(myopt -> Automatic)),
otherargsandopts)
Example: Fourier rescaled
Let's try it out. We redefine Fourier in order to divide its result by the square root of the length of the list passed to it. This is the result of the built-in procedure Fourier in a fresh Mathematica kernel:
Fourier[{1, 2, 3, 4}] // Chop
{5., -1. - 1. I, -1., -1. + 1. I}
If we redefine the procedure in a way that it can call itself:
$override = True;
Unprotect[Fourier];
Fourier[data_List ] /; $override == True := Block[{$override = False},
Fourier[data]/Sqrt[Length[data]]
];
Protect[Fourier];
We can have a new version of Fourier that works according to our taste (on version 4 we should consider the option for FourierParameters, while on previous versions the new definition can be used to add exactly that option).
Fourier[{1, 2, 3, 4}] // Chop
{2.5, -0.5 - 0.5 I, -0.5, -0.5 + 0.5 I}
Tah dah!
To go back to 'factory settings' we just clear our definition
Unprotect[Fourier]; Clear[Fourier]; Protect[Fourier];
The following conditional assignment allows for another kind of unsetting, since it is possible to use the form of the left hand side to choose the assignment we did (this one come from Villegas' tutorial on working with unevaluated expressions - I wish I had read it before creating my packages)
Unprotect[Fourier];
Unset[Fourier[data_List] /; $override == True];
Protect[Fourier];
Expectation. Could you not write your own function to callmyExpectation[expr_]when desired andExpectationotherwise? – JimB Sep 28 '15 at 04:45Unprotectto modify the definition and indeed, had submitted that as my answer to my own question. But upon testing that method further --- even if I work it inside aModule, hoping that variable scoping would limit the effects ofUnprotect(it didn't) --- my approach was behaving very unexpectedly. In the end, I ended up doing something what you'd suggested. Thanks for the thought! – user32416 Sep 28 '15 at 05:38Expectationis inefficient? If you can give a relatively clear example we might be able to improve the built-in methods! – Stefan R Sep 28 '15 at 20:02