Is there any way to "close" a package (or a symbol, or a context) in that if a user of the package adds definitions to the symbol they will be tried before the package defined ones, just like what happens with built-ins?
|
I will suggest a solution for A first ingredient of my suggestion is a (slightly modified) symbol-cloning functionality described here:
Here comes my suggested dynamic environment then:
What is happening here: first, we clone the original symbol. Then, we Here comes an example:
And now:
you can see that in the first two cases, the modified definitions were used, in the third one the original definition was used, and the last one did not match any and evaluated to itself. One can nest these constructs, and the inner one will override the outer ones then. For example:
You can ask why I wasn't just using the Villegas-Gayley trick by itself, which is much simpler. The answer is that there is no guarantee that the ordering of definitions will be right with it, even if we manually reorder them, and moreover, cases like The suggested approach is as good as the symbol's cloning procedure is. For |
||||
|
|
|
If we are the ones writing the package in question, then we could proceed as follows. First, we define a public version of the function that delegates all calls to a private version:
Then we define the functionality we desire on the private function:
Before users make any modifications, the public function behaves in the way we have defined:
Now, if a user comes along and adds a definition to the public function...
... then the corresponding behaviour is overridden, but the other definitions remain in place.
Since the public function is defined with the broadest possible definition, all more-specific user definitions will be tried before the pre-defined rules. Of course, if the user redefines the public function's one definition exactly, then all bets are off. Handling Partial Functions If the function is only partially defined, we may want the public function to return unevaluated when the arguments are outside its domain. To do this, we need a slightly more elaborate version of the public function:
Unfortunately, Mathematica no longer considers this definition to be "broad" due to the complex
We'll change
Users can then add further partial definitions:
|
|||||||||||||
|
|
Here is method based on WReach's answer. It works by explicitly sorting the list of
Testing:
|
|||||||||||||
|
|
Ok, based on your answers...
This doesn't suffer problems of the automatic
Now, making some definitions
We see that
returns
|
|||
|
|

Parallel*functions, are actually implemented as a package!! – Szabolcs Mar 14 '12 at 19:37ParallelSubmit[___]:=8after unprotecting... It gets added at the bottom of the DownValue list andParallelSubmit[2+2]works "as usual" instead of catching the new definition – Rojo Mar 14 '12 at 22:27withUserDefs[ParallelSubmit, {SetAttributes[ParallelSubmit, HoldAllComplete]; ParallelSubmit[__] := 8}, ParallelSubmit[2 + 2]]. Although, tripple blank is the only pattern which my method does not currently cover. – Leonid Shifrin Mar 15 '12 at 0:09