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.