D2 Short list -- opSlice

Denis Koroskin 2korden at gmail.com
Thu Nov 19 01:03:39 PST 2009


On Thu, 19 Nov 2009 11:53:51 +0300, Don <nospam at nospam.com> wrote:

> Andrei Alexandrescu wrote:
>> We're entering the finale of D2 and I want to keep a short list of  
>> things that must be done and integrated in the release. It is clearly  
>> understood by all of us that there are many things that could and  
>> probably should be done.
>>  1. Currently Walter and Don are diligently fixing the problems marked  
>> on the current manuscript.
>>  2. User-defined operators must be revamped.
>
> Should opIndex and opSlice be merged?
> This would be simpler, and would allow multi-dimensional slicing.
> Probably the simplest way to do this would be to use fixed length arrays  
>   of length 2 for slices.
> So, for example, if the indices are integers, then
> opIndex(int x) { } is the 1-D index, and
> opIndex(int[2] x) {} is a slice from x[0] to x[1],
> which exactly corresponding to the current opSlice(x[0]..x[1]).
>
> Since fixed-length arrays are now passed by value (yay!) this would be  
> just as efficient as the current method. It'd be simple to implement.
>
> Downsides: (1) Arguably not terribly intuitive.
> (2) This would not let you have a slicing from A..A, while  
> simultaneously allowing indexing by A[2]. But I don't think that makes  
> sense anyway -- what would $ return? (Note that it doesn't stop you from  
> having indexes of type A[2], and slice from A[2]..A[2], which might be  
> important for containers of 2D vectors. It's only the case where  
> indexing and slicing are different types, which is prohibited).
>
> This is the only solution I have which doesn't introducing more coupling  
> between the language and standard library.
> Another possible solution is to define a special Slice struct in  
> std.object; downside is that it creates yet another pseudo-keyword.
>
> A third solution would be to use tuples;  currently I think it's  
> impossible, but if tuple auto-flattening is removed there may be a  
> chance. Even so, it might be a little clumsy to use.
>
> A fourth solution is to retain the status quo, and not provide the  
> multi-dimensional slicing feature <g>. This is actually about the same  
> amount of work as option (1), since opDollar would need to work for  
> opSlice (I only implemented it for opIndex).

I'd like for a..b to be auto-magically rewritten into range(a, b). This  
way you can distinguish between indexing and slicing:

struct Range
{
    T lower, upper;
    // front, back, popFront, popBack, empty
}

Range!(T) range(T)(T lower, T upper) {
    return Range!(T)(lower, upper);
}

auto opIndex(Range!(int) range) { // corresponds to foo[a..b];
}

auto opIndex(int index1, int index2) {  // corresponds to foo[a, b];
}

This will also get rid of a special case inside foreach:

foreach (i; a..b) {
}

since a..b will be converted into a range, generic rules would apply to it.



More information about the Digitalmars-d mailing list