Re: Unprotect
- To: mathgroup at smc.vnet.net
- Subject: [mg120900] Re: Unprotect
- From: "Oleksandr Rasputinov" <oleksandr_rasputinov at hmamail.com>
- Date: Sun, 14 Aug 2011 20:19:12 -0400 (EDT)
- Delivered-to: l-mathgroup@mail-archive0.wolfram.com
- References: <j28elu$3ev$1@smc.vnet.net>
On Sun, 14 Aug 2011 13:22:22 +0100, Themis Matsoukas <tmatsoukas at me.com>
wrote:
> I want to redefine a build in command. I use the following example:
>
> Unprotect[Entropy];
> Entropy[x_] := 1/x
> Entropy[10.]
>
> When I execute these commands on a fresh kernel I get:
>
> SetDelayed::write: Tag Entropy in Entropy[x_] is Protected. >>
>
> $Failed
>
> Entropy::targ: Argument 10.` at position 1 should be a List, a
> SparseArray, or a String. >>
>
> Entropy[10.]
>
> If I execute a second time I get my definition to work but I still get a
> warning about the arguments:
>
> Entropy::targ: Argument 10.` at position 1 should be a List, a
> SparseArray, or a String. >>
>
> 0.1
>
> So, two questions:
> 1. Do I have to execute twice to cause a custom definition to stick?
> 2. How do I get rid of the warning once the custom definition works?
>
> Running 8.01 on Lion.
>
> {"8.0 for Mac OS X x86 (64-bit) (February 24, 2011)", 1}
>
> Themis
>
This is a bit of an awkward situation. The reason your Unprotect did not
work is because Entropy is an AutoLoad function and is redefined when
first referenced. In a new session:
ClearAttributes[Entropy, ReadProtected];
?? Entropy
prints:
Attributes[Entropy]={Protected}
Entropy :=
System`Dump`AutoLoad[Hold[Entropy],
Hold[GeometricMean, HarmonicMean, ContraharmonicMean,
RootMeanSquare, MeanDeviation, MedianDeviation, Skewness,
Kurtosis, TrimmedMean, Quartiles, InterquartileRange,
QuartileDeviation, QuartileSkewness, Commonest, Covariance,
Correlation, Standardize, Entropy], "Statistics`Descriptive`"] /;
System`Dump`TestLoad
So the key is to reference Entropy before Unprotecting. In another new
session:
Entropy;
ClearAttributes[Entropy, ReadProtected];
?? Entropy
prints:
Attributes[Entropy]={Protected}
Entropy[Statistics`DescriptiveDump`args___] :=
Block[{Statistics`DescriptiveDump`res =
Catch[Statistics`DescriptiveDump`iEntropy[
Statistics`DescriptiveDump`args]]},
Statistics`DescriptiveDump`res /;
Statistics`DescriptiveDump`res =!= $Failed]
Options[Entropy]={SameTest->Automatic}
which is the proper definition which we may now Unprotect and update:
In[6] :=
Unprotect[Entropy];
Entropy[x_] := 1/x;
Entropy[10.]
giving:
During evaluation of In[6]:= Entropy::targ: Argument 10.` at position 1
should be a List, a SparseArray, or a String. >>
Out[8] =
0.1
leaving us the message to deal with. This occurs because the order of
DownValues matters, and your DownValue was defined after the built-in one.
Mathematica tries to re-order DownValues so that the more specific cases
are first, but in this case it does not seem to have succeeded, probably
because it is not very clear which of the two DownValues should be
considered more specific than the other. At any rate, one can re-order the
DownValues manually:
DownValues[Entropy] = Reverse@DownValues[Entropy, Sort -> False];
Now we have:
In[10] :=
Entropy[10.]
Out[10] =
0.1
which is as desired.
Note that the above technical explanation is not intended as a commentary
on whether or not it is a good idea to re-define built-in symbols in this
way. In general, it is better not to do so unless you have a good reason
for it since many Mathematica functions are interdependent and redefining
them can lead to unexpected problems.