November 10, 2006
> Wouldn't that be -1? But the point stands.

Ah, yes of course.

> Also how do you get a 0 length slice with inclusive?
> exclusive
> data[0..0].length == 0;
> inclusive
> data[0..0].length == 1;

Hmm, why it's so important ?
November 10, 2006
arr[1 ..= 5] is cool for inclusive.. but...
arr[1 -> 5] is simple and the -> isn't being used in D anyways.. It could be the
inclusive range.. TROUGH....

Eh?

'->' for president!!
November 10, 2006
== Quote from %u (trevorparscal@hotmail.com)'s article
> I'm learning ruby right now, and I noticed they use a very cool
syntax for ranges.
> 0..5 means 0, 1, 2, 3, 4, 5
> 0...5 means 0, 1, 2, 3, 4
> The current array slicing is useful half the time and a pain in the
arse the
> other half, so I was wondering if anyone else has mentioned this
idea for D
> before...
> - Trevor

Well, the difference is that in D 0..5 doesn't mean 0,1,2,3,4,5, but 'starting from 0, 5 positions'.

thus, if you want 0,1,2,3,4 you use, well, 0..4.

I know what you mean, though, if you have 1..x you need sometimes to use 1..x-1, but hey, it doesn't look that bad, and having two different yet very simillar notations for 'inclusive' and 'exclusive' sounds like a great srouce of bugs.

Cheers,
Mariano.
Mariano.

November 10, 2006
Nikita Kalaganov wrote:
>>Wouldn't that be -1? But the point stands.
> 
> 
> Ah, yes of course.
> 
> 
>>Also how do you get a 0 length slice with inclusive?
>>exclusive
>>data[0..0].length == 0;
>>inclusive
>>data[0..0].length == 1;
> 
> 
> Hmm, why it's so important ?

int[] a, b, c;
a = ...
b = ...


// insert before i
int i = ...;

	// exclusive slices
c = a[0..i] ~ b ~ a[i..$];

//vs.

	// inclusive slices
if(i==0)
	c = b ~ a;
else if(i == a.length)
	c = a ~ b;
else
	c = a[0..i-1] ~ b ~ a[i..$];

having the identity a == a[0..i]~a[i..$] is nice.
November 10, 2006
Walter Bright wrote:
> %u wrote:
> 
>> I'm learning ruby right now, and I noticed they use a very cool syntax for ranges.
>>
>> 0..5 means 0, 1, 2, 3, 4, 5
>> 0...5 means 0, 1, 2, 3, 4
>>
>> The current array slicing is useful half the time and a pain in the arse the
>> other half, so I was wondering if anyone else has mentioned this idea for D
>> before...
> 
> 
> I have a bit of a problem with .. vs ..., I think they both look too similar  making it hard to review code for correctness, and I'd have a hard time remembering which means which, another source of bugs.

When I tried to solve the problem, the best I could come up with was
[0..5] 0,1,2,3,4,5
[0..5<] 0,1,2,3,4
[>0..5] 1,2,3,4,5
[>0..5<] 1,2,3,4

I feel that [> and <] are reasonnably intuitive operators.

But it change D's default so I suppose that this isn't possible as this means that D[0..length] would have to be replaced by D[0..length<] or introducing a new keyword D[0..last] 'last' being length-1 of course, the index of the last element of the array.

Regards,
RenoX
November 10, 2006
Fredrik Olsson wrote:
> I also like to yet again say that having ranges as a type that can easily be based around would be neat.
> 
> bool checkAge(int age, int min, int max) { ... }
> auto ok = checkAge(bar, 18, 25);
> or
> bool checkAge(int age, int$ range) { ... }
> auto ok = checkAge(bar, 18...25);
> 
> Well how to denote a range type, is something I have not figured out yet. So I went for a $ suffix in the example.
> 
> 
> As an extension, sets is just as useful!
> 
> int<> myFriendsAges = <18, 25, 21>;
> bool foo = allAgesInRangeOver21(myFriendsAges);
> 
> 
> And imagine slicing an array with a set!
> Person[] primePersons = allPersons[<2,3,5,7,11>];

Hmm this got me thinking, why not just use an array?

I beleive I wrote earlier that opIndex didn't work with non-int types. Apparently I was wrong.  Sorry for spreading FUD.  I think maybe what didn't work was non-int with opSlice, but that's ok, since you can easily make opIndex act like a slicer.

So how does this look?

For a Class c containing the array:
     float a[] = [10,11,12,13,14,15,16,17,18,19,20];

c[3]  =                 13
c[[1,4,2,0,7]] =        [11,14,12,10,17]
c[Range(2)] =           [12,13,14,15,16,17,18,19,20]
c[Range(2,4)] =         [12,13]
c[Range(2,8,2)] =       [12,14,16]
c[Range(2,null,2)] =    [12,14,16,18,20]
c[Range(8,2,-2)] =      [18,16,14]

For the plain array we can't overload opIndex, so we have to call a method:
     float a[] = [10,11,12,13,14,15,16,17,18,19,20];

a.slice([1,4,2,0,7]) =       [11,14,12,10,17]
a.slice(Range(2)) =          [12,13,14,15,16,17,18,19,20]
a.slice(Range(2,4)) =        [12,13]
a.slice(Range(2,8,2)) =      [12,14,16]
a.slice(Range(2,null,2)) =   [12,14,16,18,20]
a.slice(Range(2,8,-2)) =     [18,16,14]

You can even index with an array of Ranges! (If you really want to...)
c([Range(4,-1,-2), Range(5,10,2)]) = [14,13,12,11,10,15,16,17,18,19]

Also helpful methods .list and opApply:

Range(0,5).list =        [0,1,2,3,4]
Range(4,null,-1).list =  [4,3,2,1,0]
Range(0,10,2).list =     [0,2,4,6,8]
Range(8,-1,-2).list =    [8,6,4,2,0]
foreach(i,Range(0,10,2)):  0, 2, 4, 6, 8,
foreach(i,Range(8,-1,-2)):  8, 6, 4, 2, 0,
foreach(i,Range(0,null,3)):  0, 3, 6, 9, 12, ...<break>

What's not so hot, could be improved:

D Limitations:
* Can't overload opIndex for built-in arrays :-(

* Can't make the 'slice' function return a plain T for slice(int), rather than a T[].  That is, I can't figure out how to do it without breaking IFTI, and I think we can agree arr.slice!(float[],int[])([4,5,6]) pretty much kills the convenience factor.

* slice can't be extended with new native index types.  In C++ it would be possible to add custom specializations of the slice template, so I could define my own slice(T[],SetIndex) that would get looked up.  In D that gives you an IFTI error (can't specialize automatically deduced type).  The result is that in D it has to all go inside the one mondo slice template as static if cases.  3rd parties can't extend the behavior.

Limitations of my implementation:

* I focused on positive ranges, to allow indexing everthing that can be reached by a size_t, but a version using signed values might be useful too.

* A version that does inclusive ranging might be nice as well, but I couldn't think of a good way to do that without just duplicating most of the code.  Ooh, maybe you could abuse complex literals for that! Range(2, 5i) --> means 2 to 5 inclusive.  Ooh that works, it's in the attached file too.

* You could imagine adding to the slice template to support anything with an opApply that generates ints.  Or a Set type, or anything for that matter.  (But it all has to be added inside that one 'slice' template as far as I can tell.)

--bb


November 12, 2006
Daniel Keep wrote:
> 
> Pragma wrote:
> 
>>...
>>
>>The only way to satisfy all of the above cleanly, is as a library type
>>that masquerades as an array.  Something like a templated struct could
>>do the job nicely, and would cover more range types than just integer
>>sequences.  In essence, I think the need for a range type w/array
>>semantics, is one-and-the-same with the need for an iterator
>>implementation.  They're just two different flavors of the same thing:
>>one iterates an actual data set (which built-in arrays do implicitly),
>>the other pulls values out of thin air.
> 
> 
> Which brings up an interesting idea...
> 
> 
>>auto range = new Range!(int)(0,10,2); // 0-10 with 2 step
>>auto evens = someArray[range]; // extract even elements
> 
> 
> Would be really cool since you could fiddle with the range to get
> exactly the set of elements you want, and then extract them all in one
> pass.  But if you're going to do that, why not just allow the "range"
> bit be any old iterator that iterates over keys?
> 
> 
>>auto range = AllPeople.marriedIterator;
>>auto shackled = AllPeople[range];
> 
> 
> Just a thought :3 Maybe we should just MAKE a library implementation of
> a range, hand it to Walter and say "let's make this standard".
> 
> We can then write mixins to be used by library code for using ranges
> inside of opIndex; it should be possible to express opIndex(range) in
> terms of opIndex(key).  Maybe if we can a standard iterator
> interface/base class/whatever, we can do the same to allow for slicing
> using an interator.
> 
> (Also thinking out loud...)

My gut is listening, and it's starting to feel pretty good!
November 12, 2006
Mariano wrote:
> == Quote from %u (trevorparscal@hotmail.com)'s article
>> I'm learning ruby right now, and I noticed they use a very cool
> syntax for ranges.
>> 0..5 means 0, 1, 2, 3, 4, 5
>> 0...5 means 0, 1, 2, 3, 4
>> The current array slicing is useful half the time and a pain in the
> arse the
>> other half, so I was wondering if anyone else has mentioned this
> idea for D
>> before...
>> - Trevor
> 
> Well, the difference is that in D 0..5 doesn't mean 0,1,2,3,4,5, but
> 'starting from 0, 5 positions'.

No, in D a..b means "starting from a go while less than b".

--bb
1 2 3 4
Next ›   Last »