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=