July 23, 2007 Re: Foreach Range Statement | ||||
|---|---|---|---|---|
| ||||
Posted in reply to Bill Baxter | Bill Baxter a écrit :
> I really like that 5..1:-1 syntax though! Was that mentioned before? Something about all the colons in Pythons range literals always makes me uneasy. a:b:c -- is that a to c stepping by b? Or a to b stepping by c? In Python it's the latter. In Matlab I think it's the former. Which is probably why I always feel a little uneasy when I see it. But a..b:c is much clearer! Obviously it's from a to b, so c must be a step. And the colon looking like the two dots stood on end -- lovely.
Lovely, yes, that's the first time I see this syntax, it's nice, but I wonder if the 'step' part is so important that sugar syntax is needed for it.
In Ruby, they do the step part without sugar: 1..n.step(<step value>), the <step value> being optional with a default value of 1 (following a proposal of mine where they only took this part which was for me the least interesting point of the proposal *sigh*)
IMHO, it'd better to concentrate on the range syntax and to get a nice one for all the cases: closed range, open, half-open.
At one point I came with [<, [>, >], <] it's not very pretty but it's quite intuitive (at least for those who are used to math range, I bet that you guys can figure what means [<1, 5<] without I need to give explanations) it has a good visual effect I think and that contrary to just .. and ... it allows all the possibilities..
Regards,
renoX
| |||
July 24, 2007 Re: Foreach Range Statement | ||||
|---|---|---|---|---|
| ||||
Posted in reply to Bill Baxter | Bill Baxter wrote: > Don Clugston wrote: >> Bill Baxter wrote: >>> Don Clugston wrote: >>>> Reiner Pope wrote: >>>>> Bill Baxter wrote: >>>>>> Jarrett Billingsley wrote: >>>>>>> "Xinok" <xnknet@gmail.com> wrote in message news:f80qof$2n0l$1@digitalmars.com... >>>>>>> >>>>>>>> foreach(i; 0..100) >>>>>>> >>>>>>> This is almost identical to the syntax in MiniD: >>>>>>> >>>>>>> for(i: 0 .. 100) >>>>>>> >>>>>>> It could be done with for or foreach; I just chose for because normally you use for loops to iterate over ranges of integers. >>>>>>> >>>>>>> You can also come up with a pretty simple short-term solution that'll be fairly efficient (though not as efficient as if the compiler were aware of this kind of loop intrinsically) by making a struct 'range' which has a static opCall to construct a range and an opApply to iterate over the values, so that it'd look like: >>>>>>> >>>>>>> foreach(i; range(100)) >>>>>>> >>>>>>> Which isn't terrible at all. >>>>>> >>>>>> And it has the advantage of being more extensible. And for allowing ranges to be treated as first class entities that can be passed around and manipulated. But no, instead we get another one-trick pony. >>>>>> >>>>>> --bb >>>>> That was my first thought, too. >>>>> >>>>> In the "Array Slice Ranges" thread, several people mentioned first-class ranges: >>>>> >>>>> http://www.digitalmars.com/pnews/read.php?server=news.digitalmars.com&group=digitalmars.D&artnum=43865 >>>>> >>>>> http://www.digitalmars.com/pnews/read.php?server=news.digitalmars.com&group=digitalmars.D&artnum=43904 >>>>> >>>>> http://www.digitalmars.com/pnews/read.php?server=news.digitalmars.com&group=digitalmars.D&artnum=43905 >>>>> >>>>> http://www.digitalmars.com/pnews/read.php?server=news.digitalmars.com&group=digitalmars.D&artnum=43954 >>>>> >>>>> >>>>> Your implementation, Bill, seems to be just right, and gives you foreach over ranges for free. >>>>> >>>>> What's wrong with adding that to the language, but templated and with nice syntax? >>>>> >>>>> type name literal >>>>> int..int (range of int) 1..5 >>>>> int..double (range of int to double) 1..5.0 >>>>> int..int:int (stepped range) 5..1:-1 >>>>> >>>>> (I'm not sure of the use of mixed-type ranges, but this seems the most intuitive syntax. Since most ranges are probably of one type, how about allowing a symbol to denote "same type again". Any of the following could mean int..int: int..#, int.._, int..$) >>>> >>>> I don't think it make sense to have mixed type ranges. The normal promotion rules should apply. However... >>>> >>>> Floating-point ranges are tricky. Should they be open-ended, or closed-ended? >>> >>> Both Matlab and Numpy have floating point ranges. Matlab ranges are always inclusive, so 1:2.1:7.3 gives you 1.0, 3.1, 5.2, 7.3. Python ranges are always non-inclusive, so it gives you 1.0,3.1,5.2. >>> >>>> Consider >>>> -real.infinity..real.infinity >>>> Are the infinities part of the range? If not, how do you specify a range which includes infinity? >>> >>> Does it matter that much? I suppose it would be cool if it did something really consistent, but Numpy just craps out and gives you an empty list, and Matlab raises an error "Maximum variable size allowed by the program is exceeded". >> >> I think that if you can't specify a range including an infinity, then floating point ranges don't make sense. Especially, I really don't like the idea that -real.infinity..real.infinity would include -infinity, but not +infinity. > > I've had a use for floating-point ranges: specifying domain and range of > > functions, where infinity is fairly common. When else would you use them? > > > > It sounds like maybe you're talking about "intervals" rather than "ranges". Yes, definitely intervals should be able to handle infinities correctly. But a range (a la python or matlab) is a shortcut for a sequence of values, with equal-size steps in between beginning and end. OK, that makes sense. Although, for the integer case it's clear how many elements are in a range; it's not at all obvious for floating point. > To have the beginning or end be infinite is asking for trouble. For instance in Matlab that tries to allocate an infinite-sized array of numbers. Agreed. Although 0..infinity is only one element bigger than 0..real.max. > >> Besides, "first_element .. last_element-1" doesn't work for (say) >> 0.00001 .. 0.00003; > > Sure it does. It's just a set containing only 0.00001. I don't know what you mean by -1 there. I mean, in the floating point case, you can't work out the last element of the range by subtracting 1 from it. >> But we probably don't want 1.0..5.0 to contain 5.0 when 1..5 doesn't contain 5. > > Right. Numpy had the same problem. Python itself uses the same non-inclusive rule as D. But Python only handles integers in things like the "range(start,end,step)" function. The Numpy folks wanted to extend that to work for floating point types as well. But actually, in both matlab and numpy, if you want an evenly spaced set of numbers, you usually use the 'linspace' function, which has the signature linspace(begin,end,numvals). This creates an inclusive array of numbers. That makes sense. You could also have a logarithmic range. But what need is there for using ".." with floating point numbers? Surely we can already write foreach(float x, linspace(begin, end, numvals)){} > I think one source of confusion is that ranges and slices are very similar things, but not quite the same. > > * A range is just a sequence of numbers. It can exist and be interpreted independently. Here allowing floating point numbers makes sense. Allowing for infinity may make sense, but practically it's very niche. Iterating over infinite things usually takes either too much time or too much memory. How is that different to a set? I've always assumed a range (a,b) contained EVERYTHING between a and b. I'm not very familiar with either Python or Matlab. > * A slice needs an object to operate on for interpretation of object-relative things like $. Generally speaking, only integers make sense in a slice. Infinity doesn't really make sense because you can't generally have things that are both slice-able and infinite on a computer. > > (* An interval just represents two points on a numberline, plus maybe an indication of the inclusivity of the endpoints. Infinity -- ok. Floating point -- ok.) > > It may be possible to combine the concepts into one type, but they *are* slightly different, and may benefit from being treated as so. That clarification is very helpful. Thanks. | |||
July 24, 2007 Re: Foreach Range Statement | ||||
|---|---|---|---|---|
| ||||
Posted in reply to Don Clugston | Don Clugston wrote: > OK, that makes sense. Although, for the integer case it's clear how many elements are in a range; it's not at all obvious for floating point. > >> To have the beginning or end be infinite is asking for trouble. For instance in Matlab that tries to allocate an infinite-sized array of numbers. > > Agreed. Although 0..infinity is only one element bigger than 0..real.max. Either way, it's still going to be a memory error in Matlab. The real.max one would probably be a memory error in Numpy too. >> >> Right. Numpy had the same problem. Python itself uses the same non-inclusive rule as D. But Python only handles integers in things like the "range(start,end,step)" function. The Numpy folks wanted to extend that to work for floating point types as well. But actually, in both matlab and numpy, if you want an evenly spaced set of numbers, you usually use the 'linspace' function, which has the signature linspace(begin,end,numvals). This creates an inclusive array of numbers. > > That makes sense. You could also have a logarithmic range. Yes, both have a "logspace" function as well. > But what need is there for using ".." with floating point numbers? Surely we can already write > foreach(float x, linspace(begin, end, numvals)){} I can't really think of any super duper reason. It's just a shortcut for: for(float x=0.0; x<end; x+=0.1) { } I've used it in Python before. I think I used it more in Matlab, though, where the ranges are inclusive. >> I think one source of confusion is that ranges and slices are very similar things, but not quite the same. >> >> * A range is just a sequence of numbers. It can exist and be interpreted independently. Here allowing floating point numbers makes sense. Allowing for infinity may make sense, but practically it's very niche. Iterating over infinite things usually takes either too much time or too much memory. > > How is that different to a set? I've always assumed a range (a,b) contained EVERYTHING between a and b. I'm not very familiar with either Python or Matlab. Yes. It is just a set. An ordered set with fixed spacing between elements, expressed using a compact notation. >> * A slice needs an object to operate on for interpretation of object-relative things like $. Generally speaking, only integers make sense in a slice. Infinity doesn't really make sense because you can't generally have things that are both slice-able and infinite on a computer. >> >> (* An interval just represents two points on a numberline, plus maybe an indication of the inclusivity of the endpoints. Infinity -- ok. Floating point -- ok.) >> >> It may be possible to combine the concepts into one type, but they *are* slightly different, and may benefit from being treated as so. > > That clarification is very helpful. Thanks. --bb | |||
Copyright © 1999-2021 by the D Language Foundation
Permalink
Reply