Re: Assigning part of indexed object

• To: mathgroup at smc.vnet.net
• Subject: [mg119844] Re: Assigning part of indexed object
• From: Leonid Shifrin <lshifr at gmail.com>
• Date: Sat, 25 Jun 2011 05:28:10 -0400 (EDT)
• References: <itsjn7\$8u7\$1@smc.vnet.net>

```Hi Fabrice,

My guess is that the reasons are efficiency and immutability of  expressions
in Mtahematica. By restricting Set
to variables or array elements, one can connect it directly to the internal
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 that
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 disaster,
because modifying Set in such
a fashion is  dangerous, not to mention that it will often be completely
unacceptable performance-wise. Let us say
you store a large array in a symbol and use a For loop with array indexing.
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 may
never be able to identify.

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:

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 own
data type and introduce your own
assignment operator(s) - in this way, you don't have to modify Set at all.

Regards,
Leonid

On Fri, Jun 24, 2011 at 3:46 PM, Fabrice P. Laussy <
fabrice.laussy at n0spam-gmail.com> wrote:

> Dear all,
>
> Thanks for the solution. Supplemented with Oleksandr Rasputinov's fix:
>
> > Unprotect[Set];
> > Set[sym_[[part_]], val_] := sym = ReplacePart[sym, part -> val];
> > Protect[Set];
>
> it works splendidly.
>
> In "some elements of Mathematica Design (1992)" [http://goo.gl/nm1tT],
> Stephan Wolfram makes a point where one should resist the temptation to
> design functions to do things that look natural for them to do, as they
> could break dramatically later on.
>
> Here we have a clear case where Set seems it ought to work as redesigned by
> Oleksandr. Is there any reason for this not being the default behaviour?
>
>

```

• Prev by Date: Re: parsing a strig
• Next by Date: Re: How can I concatenate elements
• Previous by thread: Re: Assigning part of indexed object
• Next by thread: Re: Assigning part of indexed object