Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

part assigned sequence behavior puzzling

34 views
Skip to first unread message

mkr

unread,
Nov 25, 2009, 2:31:25 AM11/25/09
to
I am puzzled by the following behavior:

tmp = Range[15]
tmp[[7]] = Sequence @@ Range[2];
tmp[[7]] = Sequence @@ Range[2];
tmp[[7]] = Sequence @@ Range[2];
tmp

yields

{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15}
{1, 2, 3, 4, 5, 6, 1, 2, 8, 9, 10, 11, 12, 13, 14, 15}

I would have expected the repeated assignment to have a repeated
effect, thus obtaining

{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15}
{1, 2, 3, 4, 5, 6, 1, 2, 2, 2, 8, 9, 10, 11, 12, 13, 14, 15}

Where/why am I wrong?

Sjoerd C. de Vries

unread,
Nov 25, 2009, 6:22:32 AM11/25/09
to
I don't think you're wrong. I was just as puzzled with this behaviour
as you. I'd say it's a bug. Just look at the following :

Using extra temporary variables works as expected:

In[283]:= tmp = Range[15];


tmp[[7]] = Sequence @@ Range[2];

tmp2 = tmp;
tmp2[[7]] = Sequence @@ Range[2];
tmp3 = tmp2;
tmp3[[7]] = Sequence @@ Range[2];
tmp3

Out[289]= {1, 2, 3, 4, 5, 6, 1, 2, 2, 2, 8, 9, 10, 11, 12, 13, 14, 15}

Using different locations in tmp works as expected:

In[295]:= tmp = Range[15];
tmp[[3]] = Sequence @@ Range[2];
tmp[[5]] = Sequence @@ Range[2];


tmp[[7]] = Sequence @@ Range[2];
tmp

Out[299]= {1, 2, 1, 2, 4, 1, 2, 6, 1, 2, 8, 9, 10, 11, 12, 13, 14, 15}

Temporarily storing tmp somewhere else works as expected:

In[311]:= tmp = Range[15];


tmp[[7]] = Sequence @@ Range[2];

tmp2 = tmp;
tmp = 0;
tmp = tmp2;


tmp[[7]] = Sequence @@ Range[2];

tmp2 = tmp;
tmp = 0;
tmp = tmp2;


tmp[[7]] = Sequence @@ Range[2];
tmp

Out[321]= {1, 2, 3, 4, 5, 6, 1, 2, 2, 2, 8, 9, 10, 11, 12, 13, 14, 15}

My original hypothesis of what happens here was that Mathematica
optimizes assignments and remembers what it last assigned to a
location in an array. If it is the same, it does nothing. This would
work for all elements except Sequence.

This hypothesis is falsified by the following tests in which I changed
the ranges:

In[392]:= tmp = Range[15];


tmp[[7]] = Sequence @@ Range[2];

tmp[[7]] = Sequence @@ Range[3];
tmp[[7]] = Sequence @@ Range[4];
tmp

Out[396]= {1, 2, 3, 4, 5, 6, 1, 2, 3, 4, 8, 9, 10, 11, 12, 13, 14, 15}

In[397]:= tmp = Range[15];
tmp[[7]] = Sequence @@ Range[4];
tmp[[7]] = Sequence @@ Range[3];


tmp[[7]] = Sequence @@ Range[2];
tmp

Out[401]= {1, 2, 3, 4, 5, 6, 1, 2, 8, 9, 10, 11, 12, 13, 14, 15}

As you can see, only the last range sticks.

A new hypothesis would be to assume that Mathematica stores lists as a
table of pointers to the list members and that a Sequence not causes
the list to get extra pointers but that the Sequence is still
invisible lurking there with a single pointer pointing to it. Copying
the array may flatten out this structure, so that every member now
gets his own pointer:

In[402]:= tmp = Range[15];
tmp[[7]] = Sequence @@ Range[2]; tmp = tmp;
tmp[[7]] = Sequence @@ Range[2]; tmp = tmp;
tmp[[7]] = Sequence @@ Range[2]; tmp = tmp;
tmp

Out[406]= {1, 2, 3, 4, 5, 6, 1, 2, 2, 2, 8, 9, 10, 11, 12, 13, 14, 15}

This seems to confirm the hypothesis.

The problem seems to be in Set, as Part works OK:
In[476]:= tmp = Range[15];
tmp[[7]] = Sequence @@ Range[2]; {tmp[[7]], tmp[[8]], tmp[[9]]}
tmp[[8]] = Sequence @@ Range[2]; {tmp[[7]], tmp[[8]], tmp[[9]]}
tmp[[9]] = Sequence @@ Range[2]; {tmp[[7]], tmp[[8]], tmp[[9]]}
tmp

Out[477]= {1, 2, 8}

Out[478]= {1, 2, 1}

Out[479]= {1, 2, 1}

Out[480]= {1, 2, 3, 4, 5, 6, 1, 2, 1, 2, 1, 2, 10, 11, 12, 13, 14, 15}

Could you report this to sup...@wolfram.com?

Cheers -- Sjoerd

mkr

unread,
Nov 25, 2009, 11:00:29 PM11/25/09
to
On Nov 25, 3:22 am, "Sjoerd C. de Vries" <sjoerd.c.devr...@gmail.com>
wrote:
> Could you report this to supp...@wolfram.com?

>
> Cheers -- Sjoerd
>
> On Nov 25, 9:31 am, mkr <mileskra...@gmail.com> wrote:
>
>
>
> > I am puzzled by the following behavior:
>
> > tmp = Range[15]
> > tmp[[7]] = Sequence @@ Range[2];
> > tmp[[7]] = Sequence @@ Range[2];
> > tmp[[7]] = Sequence @@ Range[2];
> > tmp
>
> > yields
>
> > {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15}
> > {1, 2, 3, 4, 5, 6, 1, 2, 8, 9, 10, 11, 12, 13, 14, 15}
>
> > I would have expected the repeated assignment to have a repeated
> > effect, thus obtaining
>
> > {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15}
> > {1, 2, 3, 4, 5, 6, 1, 2, 2, 2, 8, 9, 10, 11, 12, 13, 14, 15}
>
> > Where/why am I wrong?- Hide quoted text -
>
> - Show quoted text -

Thanks for the reply. I have submitted this to WRI tech support as a
possible bug, including reference to your much more thorough analysis
here.

dh

unread,
Nov 25, 2009, 11:01:47 PM11/25/09
to

mkr wrote:

>

> tmp = Range[15]

> tmp

>

> yields

>

>

> effect, thus obtaining

>

>

> Where/why am I wrong?

>

Hi,

I asked the same question some time ago.

Set(=) has the attribute SequenceHold and does NOT evaluate Sequence.

What is assigne to tmp[[7]] is simply Sequence[1,2]. You can convince

yourselfe by: ??tmp

Only when you e.g. display tmp, Sequence will be evaluated.

Daniel

Bob Hanlon

unread,
Nov 25, 2009, 11:01:58 PM11/25/09
to

As stated in the documentation for sequence: assignment and replacement functions have attribute SequenceHold

Attributes[Set]

{HoldFirst,Protected,SequenceHold}

tmp = Range[15]
tmp[[7]] = Sequence @@ Range[2];
tmp[[7]] = Sequence @@ Range[2];
tmp[[7]] = Sequence @@ Range[2];
tmp

{1,2,3,4,5,6,7,8,9,10,11,12,13,14,15}

{1,2,3,4,5,6,1,2,8,9,10,11,12,13,14,15}

tmp = Range[15]
tmp[[7]] = Sequence @@ Range[2];

tmp = tmp;


tmp[[7]] = Sequence @@ Range[2];

tmp = tmp;


tmp[[7]] = Sequence @@ Range[2];
tmp

{1,2,3,4,5,6,7,8,9,10,11,12,13,14,15}

{1,2,3,4,5,6,1,2,2,2,8,9,10,11,12,13,14,15}


Bob Hanlon

---- mkr <miles...@gmail.com> wrote:

=============

Sjoerd C. de Vries

unread,
Nov 27, 2009, 6:43:44 AM11/27/09
to
I'd say that this is not a wise design decision. IMHO, a statement
like tmp=tmp should have no effect on tmp, whereas with this
SequenceHold situation it has.

Cheers -- Sjoerd

On Nov 26, 6:01 am, Bob Hanlon <hanl...@cox.net> wrote:
> As stated in the documentation for sequence: assignment and replacement f=


unctions have attribute SequenceHold
>
> Attributes[Set]
>
> {HoldFirst,Protected,SequenceHold}
>
> tmp = Range[15]
> tmp[[7]] = Sequence @@ Range[2];
> tmp[[7]] = Sequence @@ Range[2];
> tmp[[7]] = Sequence @@ Range[2];
> tmp
>
> {1,2,3,4,5,6,7,8,9,10,11,12,13,14,15}
>
> {1,2,3,4,5,6,1,2,8,9,10,11,12,13,14,15}
>
> tmp = Range[15]
> tmp[[7]] = Sequence @@ Range[2];
> tmp = tmp;
> tmp[[7]] = Sequence @@ Range[2];
> tmp = tmp;
> tmp[[7]] = Sequence @@ Range[2];
> tmp
>
> {1,2,3,4,5,6,7,8,9,10,11,12,13,14,15}
>
> {1,2,3,4,5,6,1,2,2,2,8,9,10,11,12,13,14,15}
>
> Bob Hanlon
>

da...@wolfram.com

unread,
Nov 30, 2009, 6:12:34 AM11/30/09
to
> I'd say that this is not a wise design decision. IMHO, a statement
> like tmp=tmp should have no effect on tmp, whereas with this
> SequenceHold situation it has.
>
> Cheers -- Sjoerd

Perhaps so. I view it, paraphrasing Churchill, as the worst possible
design, except for all the rest.

In the alternative scenario, Sequence[...] things would (I guess) cause
immediate evaluation of the left hand side. This has some bad consequences
and maybe also raises a few questions.

Bad consequences:

(1) It changes assignment semantics.
(2) It means that deeply nested expressions cannot readily be built
because complexity of adding a level becomes worse (maybe this can largely
be short-circuited, I'm not sure).

Questions:

(1) What is the expected/intended behavior of

In[87]:= ss = {a, b, c, d}; Do[ss[[j]] = Sequence[j, j + 1], {j, Length[ss]}]
?

(2) What about
ss2 = Table[Unevaluated[Sequence[i, i^2]], {i, 4}]
?

Maybe that second one is obvious, and no different from current behavior.

All the same, I think it would not be good to have a semantics wherein the
assignment in the Do loop causes evaluation of the lhs in each iteration.

Daniel Lichtblau
Wolfram Research


> On Nov 26, 6:01 am, Bob Hanlon <hanl...@cox.net> wrote:

>> As stated in the documentation for sequence: assignment and replacement

>> f=


> unctions have attribute SequenceHold
>>
>> Attributes[Set]
>>
>> {HoldFirst,Protected,SequenceHold}
>>
>> tmp = Range[15]
>> tmp[[7]] = Sequence @@ Range[2];
>> tmp[[7]] = Sequence @@ Range[2];
>> tmp[[7]] = Sequence @@ Range[2];
>> tmp
>>
>> {1,2,3,4,5,6,7,8,9,10,11,12,13,14,15}
>>
>> {1,2,3,4,5,6,1,2,8,9,10,11,12,13,14,15}
>>
>> tmp = Range[15]
>> tmp[[7]] = Sequence @@ Range[2];
>> tmp = tmp;
>> tmp[[7]] = Sequence @@ Range[2];
>> tmp = tmp;
>> tmp[[7]] = Sequence @@ Range[2];
>> tmp
>>
>> {1,2,3,4,5,6,7,8,9,10,11,12,13,14,15}
>>
>> {1,2,3,4,5,6,1,2,2,2,8,9,10,11,12,13,14,15}
>>
>> Bob Hanlon
>>

Sjoerd C. de Vries

unread,
Dec 1, 2009, 4:13:18 AM12/1/09
to
Hi Daniel,

Actually, in all my years with Mathematica I haven't had a single
occasion in which Sequence would used in this way, so perhaps the
whole discussion is moot.

> (1) What is the expected/intended behavior of
>
> In[87]:= ss = {a, b, c, d}; Do[ss[[j]] = Sequence[j, j + 1], {j,
> Length[ss]}]

Well, I know now that it is supposed to be {1, 2, 2, 3, 3, 4, 4, 5},
but my intuition would say {1, 2, 3, 4, 5, b, c, d}.

Look at this sequence (sic) of instructions (and execute it as a
whole):

s = {1, 2, 3}
s[[1]] = Sequence[4, 5]
s[[1]]
s[[2]]
s[[2]] = DifferentValueForIndex2
s[[2]]
s

The first time you ask for the contents of s[[2]] it is 5 (and this is
the only 5 you put in the list), then you assign something else to s
[[2]], so any average programmer would think the 5 is gone out of the
list now. But, surprise, there it still is... big magic

I'd say if you can check and use the value at index 2 for
calculations, you should be able to set the value at index 2, but you
can't in this case.

I wonder how many of your colleagues, when shown the subsequence of

s[[2]]
s[[2]] = DifferentValueForIndex2
s[[2]]

without showing them the first part, will be utterly amazed, and won't
know what's causing this.

Cheers -- Sjoerd

On Nov 30, 1:12 pm, d...@wolfram.com wrote:
> > I'd say that this is not a wise design decision. IMHO, a statement
> > like tmp=tmp should have no effect on tmp, whereas with this
> > SequenceHold situation it has.
>
> > Cheers -- Sjoerd
>
> Perhaps so. I view it, paraphrasing Churchill, as the worst possible
> design, except for all the rest.
>
> In the alternative scenario, Sequence[...] things would (I guess) cause

> immediate evaluation of the left hand side. This has some bad consequence=


s
> and maybe also raises a few questions.
>
> Bad consequences:
>
> (1) It changes assignment semantics.
> (2) It means that deeply nested expressions cannot readily be built

> because complexity of adding a level becomes worse (maybe this can largel=


y
> be short-circuited, I'm not sure).
>
> Questions:
>
> (1) What is the expected/intended behavior of
>

> In[87]:= ss = {a, b, c, d}; Do[ss[[j]] = Sequence[j, j + 1], {j, Le=


ngth[ss]}]
> ?
>
> (2) What about
> ss2 = Table[Unevaluated[Sequence[i, i^2]], {i, 4}]
> ?
>
> Maybe that second one is obvious, and no different from current behavior.
>

> All the same, I think it would not be good to have a semantics wherein th=


e
> assignment in the Do loop causes evaluation of the lhs in each iteration.
>
> Daniel Lichtblau
> Wolfram Research
>
> > On Nov 26, 6:01 am, Bob Hanlon <hanl...@cox.net> wrote:

> >> As stated in the documentation for sequence: assignment and replacemen=

0 new messages