www.digitalmars.com         C & C++   DMDScript  

digitalmars.D - Array Slice Ranges

reply %u <trevorparscal hotmail.com> writes:
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
Nov 08 2006
next sibling parent reply Walter Bright <newshound digitalmars.com> writes:
%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.
Nov 08 2006
next sibling parent reply Alexander Panek <a.panek brainsware.org> writes:
I'd really like to have a distinction between exclusive and inclusive 
slicing. Maybe '..'(inclusive) and '..-'(exclusive) or similar, with 
'..' => '..-'. Not *that* beautiful, though .. maybe someone has a 
better suggestion.

Alex


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.
Nov 08 2006
parent reply Mike Parker <aldacron71 yahoo.com> writes:
Alexander Panek wrote:
 I'd really like to have a distinction between exclusive and inclusive 
 slicing. Maybe '..'(inclusive) and '..-'(exclusive) or similar, with 
 '..' => '..-'. Not *that* beautiful, though .. maybe someone has a 
 better suggestion.
 
What about leaving ... as is and using ..+, or ...+, for inclusive?
Nov 09 2006
next sibling parent reply Ary Manzana <ary esperanto.org.ar> writes:
Mike Parker escribió:
 Alexander Panek wrote:
 I'd really like to have a distinction between exclusive and inclusive 
 slicing. Maybe '..'(inclusive) and '..-'(exclusive) or similar, with 
 '..' => '..-'. Not *that* beautiful, though .. maybe someone has a 
 better suggestion.
What about leaving ... as is and using ..+, or ...+, for inclusive?
I think the best approach is to use standard mathematical notation: array[1 .. 5] == 1, 2, 3, 4, 5 array(1 .. 5] == 2, 3, 4, 5 array[1 .. 5) == 1, 2, 3, 4 array(1 .. 5) == 2, 3, 4 There's no confusion there when you know mathematical ranges. The only problem is it's a confusion to the compiler... maybe?
Nov 09 2006
parent reply rm <roel.mathys gmail.com> writes:
Ary Manzana wrote:
 Mike Parker escribió:
 Alexander Panek wrote:
 I'd really like to have a distinction between exclusive and inclusive 
 slicing. Maybe '..'(inclusive) and '..-'(exclusive) or similar, with 
 '..' => '..-'. Not *that* beautiful, though .. maybe someone has a 
 better suggestion.
What about leaving ... as is and using ..+, or ...+, for inclusive?
I think the best approach is to use standard mathematical notation: array[1 .. 5] == 1, 2, 3, 4, 5 array(1 .. 5] == 2, 3, 4, 5 array[1 .. 5) == 1, 2, 3, 4 array(1 .. 5) == 2, 3, 4 There's no confusion there when you know mathematical ranges. The only problem is it's a confusion to the compiler... maybe?
well if compiler issues are no issues, than the most explicit would be: array[1 .. 5] == 1,2,3,4,5 array]1 .. 5] == 2,3,4,5 array[1 .. 5[ == 1,2,3,4 array]1 .. 5[ == 2,3,4 roel
Nov 09 2006
next sibling parent reply Ary Manzana <ary esperanto.org.ar> writes:
rm escribió:
 Ary Manzana wrote:
 Mike Parker escribió:
 Alexander Panek wrote:
 I'd really like to have a distinction between exclusive and 
 inclusive slicing. Maybe '..'(inclusive) and '..-'(exclusive) or 
 similar, with '..' => '..-'. Not *that* beautiful, though .. maybe 
 someone has a better suggestion.
What about leaving ... as is and using ..+, or ...+, for inclusive?
I think the best approach is to use standard mathematical notation: array[1 .. 5] == 1, 2, 3, 4, 5 array(1 .. 5] == 2, 3, 4, 5 array[1 .. 5) == 1, 2, 3, 4 array(1 .. 5) == 2, 3, 4 There's no confusion there when you know mathematical ranges. The only problem is it's a confusion to the compiler... maybe?
well if compiler issues are no issues, than the most explicit would be: array[1 .. 5] == 1,2,3,4,5 array]1 .. 5] == 2,3,4,5 array[1 .. 5[ == 1,2,3,4 array]1 .. 5[ == 2,3,4 roel
Very nice!! The problem with "array(1 .. 5)" is it could look like a method call. But I guess the compiler could peak past the first expression after the '(' to see if it's a "..", so then it's a range expression. With "array]1 .. 5[" the compiler inmediately knows it's a range expression. But I don't know if yours is the most explicit. In mathematics the parenthesis is used to exclude a number in a range, not the inverted bracket. Anyway, it would be *great* if any of this is implemented. This way we benefit from two things: - More expressiveness in the language. - You don't have to remember that "[1 .. 5]" actually means "1, 2, 3, 4" (at first glance it looks like "1, 2, 3, 4, 5" to me), which could lead to bugs. "opSlice" should be called in any of the four cases, the compiler should choose the appropiate value to send to the method depending on the brackets/parenthesis used, but "opSplice" should be aware that the first number is inclusive, the last is exclusive (just like now). Changing this convention could break a lot of old code.
Nov 09 2006
parent Ary Manzana <ary esperanto.org.ar> writes:
Ary Manzana escribió:
 "opSlice" should be called in any of the four cases, the compiler should 
 choose the appropiate value to send to the method depending on the 
 brackets/parenthesis used, but "opSplice" should be aware that the first 
 number is inclusive, the last is exclusive (just like now). Changing 
 this convention could break a lot of old code.
Ouch, forgot to mention: changing the meaning of "[1 .. 5]" breaks old code. :-(
Nov 09 2006
prev sibling parent reply Don Clugston <dac nospam.com.au> writes:
rm wrote:
 Ary Manzana wrote:
 Mike Parker escribió:
 Alexander Panek wrote:
 I'd really like to have a distinction between exclusive and 
 inclusive slicing. Maybe '..'(inclusive) and '..-'(exclusive) or 
 similar, with '..' => '..-'. Not *that* beautiful, though .. maybe 
 someone has a better suggestion.
What about leaving ... as is and using ..+, or ...+, for inclusive?
I think the best approach is to use standard mathematical notation: array[1 .. 5] == 1, 2, 3, 4, 5 array(1 .. 5] == 2, 3, 4, 5 array[1 .. 5) == 1, 2, 3, 4 array(1 .. 5) == 2, 3, 4 There's no confusion there when you know mathematical ranges. The only problem is it's a confusion to the compiler... maybe?
well if compiler issues are no issues, than the most explicit would be: array[1 .. 5] == 1,2,3,4,5 array]1 .. 5] == 2,3,4,5 array[1 .. 5[ == 1,2,3,4 array]1 .. 5[ == 2,3,4 roel
so a[b[1..5].length] would become a[b]1..4[.length] ??
Nov 09 2006
next sibling parent BCS <BCS pathlink.com> writes:
Don Clugston wrote:
 rm wrote:
 
 well if compiler issues are no issues, than the most explicit would be:

 array[1 .. 5] == 1,2,3,4,5
 array]1 .. 5] ==   2,3,4,5
 array[1 .. 5[ == 1,2,3,4
 array]1 .. 5[ ==   2,3,4

 roel
so a[b[1..5].length] would become a[b]1..4[.length] ??
Nice one. actually I think it would be a[b]0..4[.length] I think one big killer is that syntax highlighting would be darn near impossible. Just try to get the brace matching working. .--------------. | .----. | | | | | a[b]0..4[.length] same for the math version .--------------. | .----. | | | | | a[b[1..5).length] [ matching ) ?? or what about eyeball parsing? foo( a[i..2), fn(a2..i]); what is that supposed to be? it is darn close to: foo( a[i..2]), fn(a[2..i]); and both would compile.
Nov 09 2006
prev sibling parent rm <roel.mathys gmail.com> writes:
Don Clugston wrote:
 rm wrote:
 Ary Manzana wrote:
 Mike Parker escribió:
 Alexander Panek wrote:
 I'd really like to have a distinction between exclusive and 
 inclusive slicing. Maybe '..'(inclusive) and '..-'(exclusive) or 
 similar, with '..' => '..-'. Not *that* beautiful, though .. maybe 
 someone has a better suggestion.
What about leaving ... as is and using ..+, or ...+, for inclusive?
I think the best approach is to use standard mathematical notation: array[1 .. 5] == 1, 2, 3, 4, 5 array(1 .. 5] == 2, 3, 4, 5 array[1 .. 5) == 1, 2, 3, 4 array(1 .. 5) == 2, 3, 4 There's no confusion there when you know mathematical ranges. The only problem is it's a confusion to the compiler... maybe?
well if compiler issues are no issues, than the most explicit would be: array[1 .. 5] == 1,2,3,4,5 array]1 .. 5] == 2,3,4,5 array[1 .. 5[ == 1,2,3,4 array]1 .. 5[ == 2,3,4 roel
so a[b[1..5].length] would become a[b]1..4[.length] ??
I don't know :-) In the case you give .. I'd say it's still possible to find out the correct sequencing, something like: ok, I found a range indicator (being ..), that should be surrounded by 2 two [] characters. Now, whether that's efficient, ... , that's another question. But I'm sure there are cases to be found that are always ambiguous. roel
Nov 09 2006
prev sibling parent reply Bill Baxter <wbaxter gmail.com> writes:
Mike Parker wrote:
 Alexander Panek wrote:
 
 I'd really like to have a distinction between exclusive and inclusive 
 slicing. Maybe '..'(inclusive) and '..-'(exclusive) or similar, with 
 '..' => '..-'. Not *that* beautiful, though .. maybe someone has a 
 better suggestion.
What about leaving ... as is and using ..+, or ...+, for inclusive?
Ooh, how about: [1..=3] just like for loops, the difference between inclusive and exclusive is one '=' sign for (i=0; i<10; i++) ... // exclusive for (i=0; i<=10; i++) ...// inclusive I thing the meaning of a..=b would be easier to guess and remember. --bb
Nov 09 2006
next sibling parent Alexander Panek <a.panek brainsware.org> writes:
Good point! Has my vote.

Bill Baxter wrote:
 Mike Parker wrote:
 Alexander Panek wrote:

 I'd really like to have a distinction between exclusive and inclusive 
 slicing. Maybe '..'(inclusive) and '..-'(exclusive) or similar, with 
 '..' => '..-'. Not *that* beautiful, though .. maybe someone has a 
 better suggestion.
What about leaving ... as is and using ..+, or ...+, for inclusive?
Ooh, how about: [1..=3] just like for loops, the difference between inclusive and exclusive is one '=' sign for (i=0; i<10; i++) ... // exclusive for (i=0; i<=10; i++) ...// inclusive I thing the meaning of a..=b would be easier to guess and remember. --bb
Nov 09 2006
prev sibling next sibling parent reply Nikita Kalaganov <nkalaganov icl.kazan.ru> writes:
Hmm, as far as I understand, the non-inclusive slice avoids massive '+1'
appearings in source.

For example (slice five elements]:

uint size = 5;
data[head..head + size] //is better than data[head..head + size + 1] for
inclusive
slice

But, there are better syntax available:

[2..5] means 2,3,4,5 (inclusive slice)
[2..:5] means 'take five elements, first is at index 2', to avoid '+1' problem

So, example becomes:

uint size = 5;
data[head..:size] //good, isn't it ?

---
CON: making '..' slice inclusive breaks a lot of code :(
Nov 09 2006
parent reply BCS <BCS pathlink.com> writes:
Nikita Kalaganov wrote:
 Hmm, as far as I understand, the non-inclusive slice avoids massive '+1'
 appearings in source.
 
 For example (slice five elements]:
 
 uint size = 5;
 data[head..head + size] //is better than data[head..head + size + 1] for
inclusive
 slice
 
Wouldn't that be -1? But the point stands. Also how do you get a 0 length slice with inclusive? exclusive data[0..0].length == 0; inclusive data[0..0].length == 1;
 But, there are better syntax available:
 
 [2..5] means 2,3,4,5 (inclusive slice)
 [2..:5] means 'take five elements, first is at index 2', to avoid '+1' problem
 
 So, example becomes:
 
 uint size = 5;
 data[head..:size] //good, isn't it ?
I'd go with [start->length] but thats just me.
Nov 09 2006
parent reply Nikita Kalaganov <nkalaganov icl.kazan.ru> writes:
 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 ?
Nov 09 2006
parent BCS <BCS pathlink.com> writes:
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.
Nov 10 2006
prev sibling parent Trevor Parscal <trevorparscal hotmail.com> writes:
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!!
Nov 10 2006
prev sibling next sibling parent BCS <fizzle pathlink.com> writes:
== Quote from Walter Bright (newshound digitalmars.com)'s article
 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.
That kind of error wouldn't compile, I think... Oh. I see what your saying. I didn't even notice the two examples were different. I haven't ever had trouble with the current slice syntax.
Nov 08 2006
prev sibling next sibling parent reply Trevor Parscal <trevorparscal hotmail.com> writes:
== Quote from Walter Bright (newshound digitalmars.com)'s article
 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.
Perhaps you guys aren't keen on the .. and ... But it would be nice to have some symbol mean "through" in ranges to acompany the current .. which means "until" Like.. 0 _ 5 == 0, 1, 2, 3, 4, 5 0 .. 5 == 0, 1, 2, 3, 4 Sorry - I know there's more important things to do.... Just puting my 2 cents in...
Nov 08 2006
parent reply Bill Baxter <dnewsgroup billbaxter.com> writes:
Trevor Parscal wrote:
 == Quote from Walter Bright (newshound digitalmars.com)'s article
 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.
Perhaps you guys aren't keen on the .. and ... But it would be nice to have some symbol mean "through" in ranges to acompany the current .. which means "until" Like.. 0 _ 5 == 0, 1, 2, 3, 4, 5 0 .. 5 == 0, 1, 2, 3, 4 Sorry - I know there's more important things to do.... Just puting my 2 cents in...
__ is a legal identifier though, so you'd need spaces to use it generally. Maybe arr[2~~3] -- two dots stretch out and squgglified? arr[2**2] -- two dots gone hairy? arr[2::3] -- two dots .. on top of two dots .. arr[2``3] -- closest you can get to two dots up high arr[N B] -- heh heh --bb
Nov 08 2006
next sibling parent reply Bradley Smith <digitalmars-com baysmith.com> writes:
 Maybe
 
   arr[2~~3] -- two dots stretch out and squgglified?
   arr[2**2] -- two dots gone hairy?
   arr[2::3] -- two dots .. on top of two dots ..
   arr[2``3] -- closest you can get to two dots up high

   arr[N  B] -- heh heh
 
I noticed that ~~ is listed as a token on the Lexical page (http://www.digitalmars.com/d/lex.html), but I can't find reference to it anywhere else. What is ~~ used for?
Nov 08 2006
parent Lars Ivar Igesund <larsivar igesund.net> writes:
Bradley Smith wrote:

 Maybe
 
   arr[2~~3] -- two dots stretch out and squgglified?
   arr[2**2] -- two dots gone hairy?
   arr[2::3] -- two dots .. on top of two dots ..
   arr[2``3] -- closest you can get to two dots up high

   arr[N  B] -- heh heh
 
I noticed that ~~ is listed as a token on the Lexical page (http://www.digitalmars.com/d/lex.html), but I can't find reference to it anywhere else. What is ~~ used for?
An artifact from the regex match expression I think. -- Lars Ivar Igesund blog at http://larsivi.net DSource & #D: larsivi
Nov 09 2006
prev sibling next sibling parent Trevor Parscal <trevorparscal hotmail.com> writes:
== Quote from Bill Baxter (dnewsgroup billbaxter.com)'s article
 __ is a legal identifier though, so you'd need spaces to use it generally.
 Maybe
    arr[2~~3] -- two dots stretch out and squgglified?
    arr[2**2] -- two dots gone hairy?
    arr[2::3] -- two dots .. on top of two dots ..
    arr[2``3] -- closest you can get to two dots up high

    arr[N  B] -- heh heh

 --bb
I see what you mean about _ being a legal identifier... Perhaps arr[0 .-. 5] ? Forget it.. I know there's no chance in hell this is gonna get added to the language even if magically a new symbol was made on everyone's keyboards that meant THROUGH but wasnt a - and had no other use except this specific purpose.... But I'm not angry about this, so long as walter continues working on D and doesnt retire in Florida and throw his computer away I'm happy.
Nov 08 2006
prev sibling parent Kirk McDonald <kirklin.mcdonald gmail.com> writes:
Bill Baxter wrote:
 Trevor Parscal wrote:
 == Quote from Walter Bright (newshound digitalmars.com)'s article
 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.
Perhaps you guys aren't keen on the .. and ... But it would be nice to have some symbol mean "through" in ranges to acompany the current .. which means "until" Like.. 0 _ 5 == 0, 1, 2, 3, 4, 5 0 .. 5 == 0, 1, 2, 3, 4 Sorry - I know there's more important things to do.... Just puting my 2 cents in...
__ is a legal identifier though, so you'd need spaces to use it generally.
Additionally, this 1_5 would be interpreted as the number 15, since D ignores underscores that appear in the middle of numerical literals. -- Kirk McDonald Pyd: Wrapping Python with D http://pyd.dsource.org
Nov 09 2006
prev sibling parent renox <renosky free.fr> writes:
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
Nov 10 2006
prev sibling next sibling parent reply rm <roel.mathys gmail.com> writes:
%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...
 
 - Trevor
in python you have a slice object, which you can pass like you would pass a range, works beautifully, is more powerful and in my eyes less error prone than .. or ... and I think ruby must change it <g> because ... has one point more than .. but one element less ... (these latest 3 points indicate I could go on and on ... :-) ) roel
Nov 08 2006
next sibling parent Bill Baxter <dnewsgroup billbaxter.com> writes:
rm 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
 and I think ruby must change it <g> because 
 ... has one point more than .. but one element less ... (these latest 3 
 points indicate I could go on and on ... :-) )
 
Whoa! I skimmed the ruby docs about .. vs ... a while back and I remember thinking "hey that's really cool, and easy to remember too because ... goes farther than .." I guess it was just so obvious to me that that would be their meaning that I didn't realize that Ruby had it backwards. Plus non-inclusive is generally more used in programming languages with 0-based indexing. The shorter thing should be the more common. It made total sense to me. But I was wrong. Ouch. Ruby really flubbed that one. Well D certainly won't make that mistake, because .. is already too entrenched as non-inclusive. :-) --bb
Nov 08 2006
prev sibling parent rm <roel.mathys gmail.com> writes:
rm 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...

 - Trevor
in python you have a slice object, which you can pass like you would pass a range, works beautifully, is more powerful and in my eyes less error prone than .. or ... and I think ruby must change it <g> because ... has one point more than .. but one element less ... (these latest 3 points indicate I could go on and on ... :-) ) roel
hmmm, replying to my own messages :-) slicing in python:
 str = "hello world from roel"

 str[s]
'l ol'
 s = slice(1,12,2)
 str[s]
'el ol '
 s = slice(1,14,2)
 str[s]
'el ol r' so it's just a type (and yes python is a typed language :-) ) I guess it's possible to create a type Slice in D and overload the opIndex operator of another type to accept a Slice type as argument.
Nov 09 2006
prev sibling next sibling parent "Kristian Kilpi" <kjkilpi gmail.com> writes:
On Thu, 09 Nov 2006 06:52:40 +0200, %u <trevorparscal hotmail.com> 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 ar=
se =
 the
 other half, so I was wondering if anyone else has mentioned this idea =
=
 for D
 before...

 - Trevor
I wouldn't mind that the following would be possible in D: 1 .. 3 =3D 1, 2 1 ... 3 =3D 1, 2, 3 To me that would be easy to remember, and not too error-prone. But that'= s = just me. Then it would be fun to take turns with D and Ruby! :) Well, actually I = = think it would be fun even now because '..' means different range in D a= nd = Ruby. But if '...' is considered too similar with '..', how about the followin= g? 1 -> 3 =3D 1, 2, 3
Nov 09 2006
prev sibling next sibling parent reply Pragma <ericanderton yahoo.removeme.com> writes:
%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...
 
 - Trevor
I hope you don't mind, but I'm just thinking aloud here. I like the idea, and it has been brought up before on multiple occasions. But I don't think the syntax is going to stand up to scrutiny for a lot of reasons (many were already voiced in earlier posts). My feeling is that it's not clearly distinguished from ".." which is important since ".." only ever appears within the same context. Something that triggers a "create range" expression might be clearer: auto myRange = [0..10]; ...distinguishing from uint and int ranges is another problem. The actual "type" installed is another, which leads me into the main thrust of this post: I don't think the creation syntax is the main stumbling block for the inclusion of a range type into D. Rather, I feel that the problem is: how would any range type be implemented under-the-hood, let alone it's construction syntax? What would it need to be? I can't help but see it as a pseudo-array type, in order to allow for concatenation, slicing, array operations (when and if they're implemented), and iteration to all behave correctly. // assuming ranges play fair with arrays, how would these work? foreach(x; myRange){} myRange[1..10]; myRange.dup; myRange.length; myRange ~= anotherRange; 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. -- - EricAnderton at yahoo
Nov 09 2006
parent reply Daniel Keep <daniel.keep.lists gmail.com> writes:
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...) -- Daniel -- Unlike Knuth, I have neither proven or tried the above; it may not even make sense. v2sw5+8Yhw5ln4+5pr6OFPma8u6+7Lw4Tm6+7l6+7D i28a2Xs3MSr2e4/6+7t4TNSMb6HTOp5en5g6RAHCP http://hackerkey.com/
Nov 09 2006
parent Georg Wrede <georg.wrede nospam.org> writes:
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!
Nov 12 2006
prev sibling next sibling parent reply Fredrik Olsson <peylow gmail.com> writes:
%u skrev:
 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
My €0.02: 0..5 should mean 0,1,2,3,4. Because it does not break existing code. 0...5 should be 0,1,2,3,4,5. All other suggestion I have seen looks contrived to me. .. and ... look obviously connected somehow, and logically "... takes it one step further than ..". Perfect or not, I have not seen any suggestion that beats it. 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>]; // Fredrik Olsson
Nov 09 2006
next sibling parent Don Clugston <dac nospam.com.au> writes:
 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.
bool checkAge(int age, int..int range) { ... } ?
Nov 09 2006
prev sibling parent Bill Baxter <wbaxter gmail.com> writes:
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
Nov 10 2006
prev sibling parent reply Mariano <rotoshi yahoo.com> writes:
== 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.
Nov 10 2006
parent Bill Baxter <dnewsgroup billbaxter.com> writes:
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
Nov 12 2006