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
> 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
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).
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