17-Jan-2013 07:53, Era Scarecrow пишет:
Well got a few curious problems. Slicing doesn't seem it wants to work
as a separate type and can cause problems.
Let's take an example. Say our slice is..
struct BitArraySlice {
BitArray* ba;
ulong start, end;
}
Now how much does it depend on the bitarray that it's pointing to? If
it is a wrapper then we have a problem with range checks which should be
legal.
BitArray x = BitArray(100); //100 elements
auto sl = x[50 .. 100];
x.length = 50;
Well, the slice was invalidated by shrinking an array. I don't expect
the below to work.
sl[0] = true; //out of range! BitArray valid from 0-49, not 50-100
The good part is that error can be detected easily. In c++ for instance
it typically isn't.
The harder problem is what to do when the original BitArray goes out of
scope. I guess in case of storage allocated on heap it should work but
if on the stack it shouldn't (and can't).
That much is sorta easy to fix with a separate opIndex (and fixed
sizes), but it's possible to re-slice the dynamic array to make it
smaller. So even if we have opIndex allow out of ranges...
struct BitArray {
size_t[] store; //storage
ubyte start, end;
}
BitArray x = BitArray(100); //100 elements
auto sl = x[50 .. 100];
//likely does x.store[] = x.store[0 .. 2];
//due to compact 1 byte offsets to determine end of bitarray.
x.length = 50;
sl[0] = true; //ok, 0-64 valid on 32bit machines
sl[32] = true; //out of range! 82 past not within 0-63
That's why it's far better to allow slices to be invalidated depending
on the length parameter of BitArray pointed by. Compact array do weird
things in the previous version too.
So let's take the slice and give it the address of the storage
instead, other than it could point to a local variable it will work; But
now I have basically two definitions of bitarray, one that can be a
range/slice while the other that manages the memory and binary operators.
struct BitArraySlice {
//same as BitArray now, what advantage does this give?
size_t[] store;
ulong start, end;
}
Seems like making the slices a separate entity is going to cause more
problems (Not that they can't be solved but the advantages seem
smaller); Plus there's issues trying to get immutable/idup working.
Slices are ranges and thus are converted to array via std.array.array,
nothing to invent or re-implement.
Thoughts? Feedback? I'm about ready to drop this and resume my
previous version and enhance it with recent experiences.
Feel free to do it how you see it. It's just that I think the semantics
of the previous version can't be improved to a consistent state.
--
Dmitry Olshansky