Re: Assigning part of indexed object
- To: mathgroup at smc.vnet.net
- Subject: [mg119863] Re: Assigning part of indexed object
- From: Oleksandr Rasputinov <oleksandr_rasputinov at hmamail.com>
- Date: Sun, 26 Jun 2011 06:26:49 -0400 (EDT)
- References: <itsjn7$8u7$1@smc.vnet.net> <iu49sb$jp7$1@smc.vnet.net>
Leonid, I fully agree with all of your comments and of course you are right to point out that modifying core functions such as Set is a bad idea in general due to the likelihood of unintended consequences. Of course, the performance issue introduced for setting parts of OwnValues can be repaired to some extent: indexedQ = Function[sym, Symbol =!= Head@Unevaluated[sym] =!= Unevaluated[sym], HoldFirst ]; Unprotect[Set]; Set[(sym_?indexedQ)[[part_]], val_] := ( sym = ReplacePart[sym, part -> val]; sym[[part]] ); Protect[Set]; which restores the O(1) behaviour (albeit at the cost of an increased constant factor). But even so, I will join with you in stressing that this general approach is dangerous and should be attempted only with extreme caution, if at all. Best, O. R. On Jun 25, 10:30 am, Leonid Shifrin <lsh... at gmail.com> wrote: > Hi Fabrice, > > My guess is that the reasons are efficiency and immutability of expres= sions > in Mtahematica. By restricting Set > to variables or array elements, one can connect it directly to the intern= al > memory layout for that element. Note > that all proposed solutions are based on ReplacePart, which copies the > entire list to modify a single element. > OTOH, constructs like indexed variables are serviced by hash-tables > internally. Even if the value stored > in the hash table is a pointer to some array, that array will likely be > immutable. Whether it would be a > good idea to make it mutable I don't know, but the general ideology is th= at > expressions are immutable > in Mathematica. In other words, I don't think that the case of indexed > variables was overlooked when > designing Set - my guess is that the restriction to symbols is quite > intentional. > > Regarding the "fix", I'd consider this not a fix but a recipe for disa= ster, > because modifying Set in such > a fashion is dangerous, not to mention that it will often be completel= y > unacceptable performance-wise. Let us say > you store a large array in a symbol and use a For loop with array indexin= g. > Suddenly all your array element assignments > become O(n) time, where n is the list size, or even worse for higher > dimensional tensors, not to mention increased > memory consumption. Here is an illustration: > > In[18]:= a = Range[10000]; > > In[19]:= Unprotect[Set]; > Set[sym_[[part_]], val_] := sym = ReplacePart[sym, part -> val]; > Protect[Set]; > > In[27]:= Do[a[[i]] = a[[i]]^2, {i, Length[a]}] // Timing > > Out[27]= {1.156, Null} > > In[28]:= Unprotect[Set]; > Clear[Set]; > Protect[Set]; > > In[31]:= Do[a[[i]] = a[[i]]^2, {i, Length[a]}] // Timing > > Out[31]= {0.047, Null} > > You may do this for yourself if you wish (although I'd avoid even that= ), > but I'd strongly > advise against such modifications in production code or any code someone > else will be using. Set is one of the > most fundamental operations, and its modifications may have very far- > reaching and hard to predict consequences. > It may, for example, corrupt the system in very subtle ways, which you ma= y > never be able to identify. > > Unfortunately, the standard mechanism of "soft" system symbols overloadin= g > via UpValues does not > quite work with Set (or at least I don't know of a way to make it work) > because Set holds its argument and UpValues > can only be defined for tags not deeper than level 1 in an expression. In > this post: > > http://stackoverflow.com/questions/5886066/overloading-seta-b-a-b/588... > > I demonstrated a method, which I also don't like, but which is at least > safer because it tests for a > specific data type. Generally, the still safer way is to create your o= wn > data type and introduce your own > assignment operator(s) - in this way, you don't have to modify Set at all=