I would like to chip in in favour of the "list is value, array is container"
side of the argument. However I think that needs clarifying.

A reference is a value; the thing it refers to is a container.

An anonymous container is a container with no references from any symbol
table.  It can lose its anonymity by creating such a reference.

A list is an ordered set of references to (normally anonymous) containers.

An array is a container that contains a list.  When created, an array
contains the empty list. The operations push, pop, shift, unshift, extend,
truncate and element auto-vivify replace the value in the array with another
value similar to the old one. Assignment replaces the value in the array
with an entirely new value.

Operations on individual elements of an array do not affect the value of the
array, just the values in the containers that the array's list members refer
to.

Possible definition:

Except for "obvious" arrays and hashes (those involving "@" or "%" in the
expression), anything evaluated inside a list in R-value context is itself
in reference context.  Named arrays and hashes are in
flatten-to-reference-to-member context.  Anything evaluated inside a list in
Lvalue context is itself in reference context.  Assignment to a list
deferences successive elements of each side.  Passing a list as parameters
dereferences each element unless the prototype says otherwise.

Almost all of these containers are either elidable at compile time, or will
be needed "soon" anyway -- eg, as elements in the formal parameter list; so
there's no practical cost to this definition.


On a related topic...

I like to be able to program in a "pure functional" mode as much as
possible, mainly because it's the easiest to prove correctness, but also
because it also offers the greatest scope for compile-time optimisation.

What I would like is for the language to enable as many compile-time
optimisations as possible, by making the optimisation-friendly choices the
shorter easy-to-type defaults.

One of those, rather inobviously, is choosing pass-by-value rather than
pass-by-reference. And rather deeper pass-by-value than the sort of list
I've talked about above: a list would be a set of actual values, not a set
of references to containers containing values. And we could extend this
to things other than arrays/lists.

It's important to understand that I'm talking about the semantics of the
language, not the implementation. The point is that the implementation is
still free to pass by reference when it can be sure that the receiving
function won't fiddle with it.  That can be guaranteed if you can see (or
infer) all the way down to the leaf function calls at compile time.  (This
gets complicated at trust boundaries, but we can work on that.)

One of the things I found most irksome moving from C++ to Java was that Java
took away both "pass object by value" AND "pass object by const reference".
Couple that with some rather bad choice of "value" vs "container" in the
standard class library, and the result was that one had no way to be sure
that an object wouldn't get modified once you handed a it over as a
parameter or referent to some random method.

Since then languages such as ECMAscript have copied that behaviour, and it
seems that P6 is looking more and more like a clone of that language ... and
that worries me.

I would like to argue in favour of "pass by value" to be the default in the
absence of some explicit prototype, because it allows greater type-safety,
and because the opposite default interacts badly with out-of-order execution
such as parallelism, and bars some optimisations that can be applied to
closures. (We do want Perl to run fast on parallel hardware, don't we?)

The relationship to the array/list thing is this: that it's not just
pass-by-value to functions and methods, it's about implicit R-valueness in
any context that doesn't absolutely require L-valueness.

All this is orthogonal to the concept of "object": in C++ "an object" can be
used to implement either a value (such as "string") or a container (such as
"vector"); it would be nice to be able to do this in P6 too.

-Martin

PS: sorry for the long post...


Reply via email to