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

Bug with Sequence and Assignment by Part...

45 views
Skip to first unread message

BernieTheJet

unread,
Sep 22, 2011, 7:31:30 AM9/22/11
to
If one patches a list of items into a list using Sequence[], it
appears that Mathemaitca doesn't properly update the data structure:

temp = Range[3];
temp[[2]] = Sequence @@ {a, a, a};
temp

as expected :
-> {1, a, a, a, 3}

FullForm[temp]
also looks right:
-> List[1,a,a,a,3]

As does:
Length[temp]
-> 5

Ok, so far all is fine. But subsequent additions to the same place do
not increase the length of temp, as one might expect:
temp[[2]] = Sequence @@ {b, b, b};
temp
FullForm[temp]

-> {1, b, b, b, 3}
and -> List[1,b,b,b,3]

And, despite the Length of temp being '5', in fact there is no way to
put anything into position '5' of temp:

Length[temp]
-> 5
temp[[5]] = Sequence @@ {c, c, c}
-> Set::partw: Part 5 of {1,Sequence[b,b,b],3} does not exist. >>

Here we finally see what is going on, somewhere temp is being stored
as {1,Sequence[b,b,b],3}, but all the functions that go to request
info from it first perform the evaluation of Sequence hence returning
the expected results.

One can force Mathematica to sort things out with the otherwise meaningless:
temp=temp

Surely I am not the first to encounter this, and surely it constitutes
at least one bug, (and surely it is shouldn't be in Mathematica 8!). I mean,
it seems to me that FullForm and Length should also detect the
presence of Sequence and act differently than they do here.

Bernard

Leonid Shifrin

unread,
Sep 23, 2011, 3:47:22 AM9/23/11
to
I agree with your analysis, but I disagree with your conclusions.


> Surely I am not the first to encounter this,


Indeed:

http://groups.google.com/group/comp.soft-sys.math.mathematica/browse_thread/thread/b7303eafccee6d5a

> and surely it constitutes
> at least one bug, (and surely it is shouldn't be in Mathematica 8!).


I wouldn't be so sure. Using Sequence to insert several elements is not a
standard form of assignment.
The way I understand idiomatic Mathematica, it is a hack. The fact that you can sort
of do it does not mean that all
aspects of it must conform to your expectations. Every decent language
allows many more things than
those for which it was primarily designed. If you are exploring the darker
corners, be prepared to face the
consequences. As for Mathematica, the observed behavior is in complete agreement
with the semantics of
Set / SetDelayed (both being SequenceHold) and Sequence, and the evaluation
procedure.

So, IMO, this is not a bug. In my reply in the quoted thread, I gave some
arguments in support of this behavior.
One point was that assignments using Sequence in this manner could not be
made generally efficient,
given that lists are implemented as arrays in Mathematica . It is one thing to assign
a pointer to the Sequence
object in a pointer array (don't need resizing), and another to shift an
array of pointers to accommodate
new elements. There is no way around the fact that insertion in an array is
a linear-time operation in
the size of an array - to avoid that you'd need lists implemented as linked
lists.

Also, from the language design perspective, adding a special case to Set -
Sequence (and complicating the
evaluation semantics even more), and silently expanding / shifting arrays
(and giving assignment a linear
time complexity without giving a clue to the user) would IMO be a terribly
bad design decision, for at least two
reasons. First, Sequence is a general head, and its semantics are higher
level than those of the memory
operations needed to truly insert new elements into a list. Second, in Mathematica
(being so high - level) it is not always
easy to estimate the complexity of code, and I'd at least like to be sure
that a single element assignment is
always a constant - time operation.


> I mean,
> it seems to me that FullForm and Length should also detect the
> presence of Sequence and act differently than they do here.
>

IMO, this would also be bad. Sequence splicing is a result of evaluation (a
step in evaluation sequence). What you
request again requires exceptions to the main evaluation sequence. For such
a system as Mathematica,
you pay a huge price for exceptions - even in its current general form,
evaluation sequence is complex enough.
I actually think that it is this generality and consistency of evaluator
(and, more generally, the languagte) that
makes possible much of further Mathematica development and component integration.
Start adding ad hoc stuff that
*looks* convenient, and you get what many other systems offer - a bunch of
not so well integrated functionality
and inelegant languages full of magic and special cases.


Regards,
Leonid

Oleksandr Rasputinov

unread,
Sep 23, 2011, 3:48:53 AM9/23/11
to
On Thu, 22 Sep 2011 12:31:30 +0100, BernieTheJet <bernie...@gmail.com>
wrote:

Just to note:

OwnValues[temp] = {HoldPattern[temp] :> {1, Sequence[a, a, a], 3}}

so I am not sure that this can really be called a bug so much as
unintuitive behaviour when looked at from a certain perspective. Seen from
another, it would certainly be quite inconvenient if Sequence was
flattened out without even having to evaluate the expression it appears
within (for one thing, this would make SequenceHold unworkable).

David Bailey

unread,
Sep 23, 2011, 3:43:17 AM9/23/11
to
Thanks for that really fascinating example!

I must say, when I first encountered Sequence as I learned Mathematica,
I was a bit stunned because it didn't seem to fit the style of the rest
of the Mathematica language. I tend to feel that if Sequence does what
you want, use it, but it will never be a completely 'normal' function!

In your example, my guess is that there is some sort of efficiency issue
here. If updating temp[[2]] could, in effect, change the rest of the
temp array then the performance of updates of vectors might suffer.

Overall, I am glad Mathematica does not hide all its sneaky functions!

David Bailey
http://www.dbaileyconsultancy.co.uk


BernieTheJet

unread,
Sep 25, 2011, 5:42:55 AM9/25/11
to
Thank you Leonid for the link, and thank you Oleksandr for pointing me
to OwnValues, I hadn't ever used that before.

So everyone's opinion seems to be that this is not a bug and that this
construct is something of a manipulation of proper Mathematica syntax -
something approaching a hack - because Sequence is a low-level
function that one should understand Mathematica's evaluation sequence before
using. Ok, that is fine. Certainly that is one interpretation ('when
looked at from a certain perspective'). Certainly one can't claim
that the use of Sequence is hidden, or in anyway indicated to be a
'low-level' operator by its presentation in the Help, except insofar
as it is given a perfunctory presentation.

But I think that it is just as valid to say that this 'bug' it is
counter to one of my favourite Mathematica design philosophy which is,
somewhat similar to Apple in this regard, to remove all the tedious
and computer-ish work from the user's care, to take care of that
behind the scenes, while still delivering as much of the power of the
language as possible. So for users to have to understand Mathematica's
evaluation sequence, SequenceHold (which I have never once used, or
perhaps even needed), or OwnValues (ditto) in order to get logical
behaviour from a function seems to clearly go against this
philosophy. Of course one can counter that there is another design
philosophy in Mathematica of mixing the best of all worlds, and never forcing
oneself to strictly subscribe to any one design structure, which I
also support.

For me, I just guess that Sequence is a 'hack' that WRI implemented to
get around the limitation that everything be a List. A 'hack' in that
it defied their initial plan that everything be representable as
Lists, and then a 'hack' in that they couldn't get it to work in a
logical fashion in all subsequent interactions with other functions,
as seen here.

B

BernieTheJet

unread,
Sep 26, 2011, 4:15:09 AM9/26/11
to
I see that this issue has been discussed a few times in the past:

http://groups.google.com/group/comp.soft-sys.math.mathematica/browse_thread/thread/dd3efcbc74d3f85c/ba74ea32ee5b8c90

I quote D Lichtblau's quoting Churchill on this point: "the worst
possible design, except for all the rest." I mean, it isn't as if
it's really so bad, but it would be nice to be documented in the
'possible issues' part of the Help.

B

DrMajorBob

unread,
Sep 26, 2011, 4:23:58 AM9/26/11
to
Amen.

Bobby

On Sun, 25 Sep 2011 04:42:00 -0500, BernieTheJet <bernie...@gmail.com>
wrote:
--
DrMaj...@yahoo.com

Richard Fateman

unread,
Sep 26, 2011, 8:10:18 PM9/26/11
to
The pronouncement that a bug is a feature is one way to cure it.

It can be fixed another way. Though I have not pondered on all the
examples, the simplest one by DanL seems to illustrate the problem
adequately.

Here is the example.

s={1,2,3}
s[[1]]=Sequence[4,5] ... sets s to apparently {4,5,2,3} (*)
s[[2]]= aha ... sets s to apparently {4,5,aha,2,3}
NOT
{4,aha,2,3}
which illustrates that (*) is apparently not the value of s.

whereas

s={1,2,3}
s[[1]]=Sequence[4,5] ... sets s to apparently {4,5,2,3} (*)
s = s ... only change from above, insert this
s[[2]]= aha ... sets s to apparently {4,aha,2,3}
note change, in last line. s is now correct.


..........



Note that z=Sequence[4,5] is really the same as Set[z,4,5].

Here's a fix. Require that Set take exactly 2 arguments. In
particular, that
means that s[[1]]=Sequence[4,5] is ILLEGAL.
Perhaps it can be converted to mean s[[1]] = List[4,5] or {4,5}

............

Will this break stuff? Only Set of items to Sequences,
and the implicit set of a pattern x__. e.g.

f[x__]:=x
y=f[1,2,3] ... sets y to Sequence[1,2,3]

Ramifications:

I think that the old use of Sequence

stuff= Sequence [a,b,c]

is used only in this way...

f[1,2,stuff,3] to simulate f[1,2,a,b,c,3].


Now consider re-writing it this way...

new={a,b,c}
f@@Join[{1,2},new,{3}]

and if you have a pattern Sequence (e.g. stuff) you write

f@@Join[{1,2},{stuff},{3}].

I suppose one could write another program, say conjoin, which would
allow the following...

f@@conjoin[1,2,stuff,3].

Another, more wholesale change would have f[x__]:=x return a List
rather than a Sequence.

in the example above, s=s would then be required -- actually,
s=conjoin@@s, or something like that

Presumably a change of this magnitude would result in disruption of the
existing code base. On the other hand, it seems to be unacceptable to
have the insertion of the command s=s change the meaning of a program.

.....
Another run through this...

Or I suppose a hack could be put in place forcing some kind of
re-evaluation after Set[<NonAtomic>, Sequence[...]]. which was
previously mentioned but thought to be too expensive...

RJF
0 new messages