Denis Koroskin wrote:
On Mon, 19 Oct 2009 18:57:45 +0400, Leandro Lucarella <llu...@gmail.com> wrote:

Andrei Alexandrescu, el 18 de octubre a las 20:16 me escribiste:
Here's what I wrote to Walter:

====================
I'm going to suggest something terrible - let's get rid of T[new]. I
know it's difficult to throw away work you've already done, but
really things with T[new] start to look like a Pyrrhic victory. Here
are some issues:

* The abstraction doesn't seem to come off as crisp and clean as we
both wanted;

* There are efficiency issues, such as the two allocations that you
valiantly tried to eliminate in a subset of cases;

* Explaining two very similar but subtly different types to
newcomers is excruciatingly difficult (I'll send you a draft of the
chapter - it looks like a burn victim who didn't make it);

* Furthermore, explaining people when to use one vs. the other is
much more difficult than it seems. On the surface, it goes like
this: "If you need to append stuff, use T[new]. If not, use T[]."
Reality is much more subtle. For one thing, T[new] does not allow
contraction from the left, whereas T[] does. That puts T[] at an
advantage. So if you want to append stuff and also contract from the
left, there's nothing our abstractions can help you with.

I think this is getting overcomplicated. I don't see it as complex, I see
it like this:

2 types should be provided: array and slice.

array is a *real* type, storing and owning memory, it should be something
like this (conceptually):

class array(T)
{
    size_t length;
    size_t capacity;
    T[capacity] elements;
}

1) a pure reference type.
2) 1 allocation only (interior pointers are not a problem, the GC have to
   support them anyways).
3) easily appendable (capacity field).

slice should be something like this:

struct slice(T)
{
    size_t length;
    T* ptr;
}

1) a pure value type.
2) no allocation at all, *ever*.
3) not appendable at all.
4) You can change both ptr and length, and you can mutate the elements (if
   not immutable).

So a slice is a window to peek a chunk of data.

Then you have the syntax. In this discussion, T[new] is array and T[] is
slice. I find that syntax very confusing. I think it could be even better
to just put those 2 types in object.d (well, do public imports of those
2 types in object.d) and let the people write:

array!T a;
slice!T s;

The array literals should be immutable chunks of memory in the static
memory, as ClassInfo.init. The type of [1,2,3] should be, for example,
slice!(immutable int), so:
auto s = [1,2,3];
should create a slice!(immutable int) with length 3 and ptr pointing to
the static memory where the [1,2,3] was stored (this is what happens with
strings, right? So no surprises here, they are consistent).

slice.dup should return an array. If you want to just copy the length and
ptr members, use assignment (it's a value type, remember)?

auto s = [1,2,3];
auto t = s;
assert(s.length == t.length);
assert(s.ptr == t.ptr);
assert(&s != &t);

Assignment of arrays is just a pointer assignment (is a reference type):

auto a = [1,2,3].dup;
auto b = a;
assert(a is b);

array.dup returns another array. array[] returns a slice though (you can
allow implicit casting from array to slice but I don't see the point as
array[] is short enough and more explicit). slices should not be
convertible to arrays (use slice.dup for that).


Back to the syntax, I think T[new] is *really* confusing. It tell me
nothing about the type, it provides the same information as calling it
it wazzzaaap!T for me. I *really* think it would be better to call it
array!T. But if we have both types, T[] is not clear anymore that is
a slice, again, you can't figure that out. So maybe T[] should be used for
arrays, not slices; if you want some syntax sugar I think T[] is more
guessable to be an array than a slice, and it would be a little more
backward compatible. Maybe slices can be T[..], but I'm not sure is clear
enough, again I think we could live with something more explicit like
array!T and slice!T. But at least slices should be part of the language,
because that should be the type of "array literals" (damn! that didn't
sound right =P).


I'm missing something? Why this shouldn't work?


That's what was initially planned (except some nuances).

I also think we need a precedent of mapping built-in language type to a library type, starting with Array!(T) and Range!(T). We could then map V[K] to AArray!(K,V), T? to Nullable!(T) etc.

There is one big issue, though: classes and allocations via 'new' don't work with CTFE. I believe this is something that is planned (Walter once said that an entire subset of D called SafeD should work with CTFE), but it is *very* hard to implement, not feasible in a nearest future for sure.

Don't worry. It's not hugely difficult to implement, though it'll be a while before all the bugs are ironed out. Most of the difficult stuff is already in place. (The CTFE memory bug is the difficult one).

Reply via email to