July 09, 2009 Re: Number literals (Was: Re: Case Range Statement ..) | ||||
|---|---|---|---|---|
| ||||
Posted in reply to BCS | BCS wrote:
> I think this strand of the thread (and what I was talking about) was not about octal but about complexity in the lexical design. That bugzilla issue was brought up as an issue and IS the first point that comes to my mind in that direction. disallowing leading or trailing decimal points would fix that issue and I for one would approve of it on that grounds as well as the the other advantages (it's harder to read wrong for one thing).
>
Don't use them if you don't like 'em. Since these are the same rules C and C++ have used for decades, and nobody seems to have a problem lexing them, I'm not sure it's a problem worth worrying about.
| |||
July 09, 2009 Re: Case Range Statement .. | ||||
|---|---|---|---|---|
| ||||
Posted in reply to Walter Bright | On Wed, Jul 8, 2009 at 8:26 PM, Walter Bright<newshound1@digitalmars.com> wrote: > Bill Baxter wrote: >> >> I think what Jerome is getting at is that we could be getting more mileage out of the xpr1..xpr2 syntax. It would be useful syntax for more than just integral, dense ranges in foreach and slices. The equivalents I've used or seen in Ruby, Python and Matlab are more versatile than D's. Perhaps that can't be translated in any useful way to a static language like D, I dunno. But it leaves one with the feeling that D's slice literals are underpowered and that the case range thing is just plugging a hole in a dilapidated boat rather than building us a nice new sleek yacht. > > How are python's so much better? > > 1. python's ranges are exclusive of the endpoint > > 2. python doesn't have a switch statement, so case ranges being better in python makes no sense Not every one of those has every feature you could imagine. But nice things about Python's slices include: * optional step size, * step size can be negative. * nice compact notation * And the a:b syntax maps to a slice object so that you can manipulate them and pass them around. Ruby is the only one I mentioned that has both inclusive and exclusive ranges (using two dots for inclusive, three dots for exclusive). Matlab's are always inclusive. But they all have an optional step size. Python's are a little annoying in that, like D, you can't use them outside of indexing expressions. Can't even use them in loops. In NumPy, the numerical library for Python, they've invented some quirky objects like numpy.r_ which you index to create a range literal. Like >>> numpy.r_[0:4:0.5] array([ 0. , 0.5, 1. , 1.5, 2. , 2.5, 3. , 3.5]) You could do the same in D, but I don't think anyone in NumPy thinks of it as a particularly elegant way to make ranges (compared to matlab where just plain 0:4:0.5 gets you the same thing). Also you'd most often like to have that 4.0 in there, so you have to tweak the range to be [0:4.5:0.5] to get that inclusivity, because python doesn't have inclusive ranges. Not ideal. So they also have Anyway, you seem pretty satisfied with what you've got, so don't mind me. You've got to draw the line somewhere. --bb | |||
July 09, 2009 Re: Case Range Statement .. | ||||
|---|---|---|---|---|
| ||||
Posted in reply to Bill Baxter | Bill Baxter: > Python's are a little annoying in that, like D, you can't use > them outside of indexing expressions. Can't even use them in loops. > In NumPy, the numerical library for Python, they've invented some > quirky objects like numpy.r_ which you index to create a range > literal. Like > >>> numpy.r_[0:4:0.5] > array([ 0. , 0.5, 1. , 1.5, 2. , 2.5, 3. , 3.5]) > You could do the same in D, but I don't think anyone in NumPy thinks > of it as a particularly elegant way to make ranges (compared to matlab > where just plain 0:4:0.5 gets you the same thing). Also you'd most > often like to have that 4.0 in there, so you have to tweak the range > to be [0:4.5:0.5] to get that inclusivity, because python doesn't have > inclusive ranges. Not ideal. So they also have For other people here: >>> class C(object): ... def __getitem__(self, key): return key ... >>> c = C() # creation >>> c[10] 10 >>> c[10:20] slice(10, 20, None) >>> c[10:20:30] slice(10, 20, 30) >>> c[...] Ellipsis So inside __getitem__ (that's like opIndex) the key is turned into a slice object, or even into a built-in Ellipsis object :-) Bye, bearophile | |||
July 09, 2009 Re: Case Range Statement .. | ||||
|---|---|---|---|---|
| ||||
Posted in reply to Bill Baxter | Bill Baxter wrote:
> On Wed, Jul 8, 2009 at 8:26 PM, Walter Bright<newshound1@digitalmars.com> wrote:
>> Bill Baxter wrote:
>>> I think what Jerome is getting at is that we could be getting more
>>> mileage out of the xpr1..xpr2 syntax. It would be useful syntax for
>>> more than just integral, dense ranges in foreach and slices. The
>>> equivalents I've used or seen in Ruby, Python and Matlab are more
>>> versatile than D's. Perhaps that can't be translated in any useful
>>> way to a static language like D, I dunno. But it leaves one with the
>>> feeling that D's slice literals are underpowered and that the case
>>> range thing is just plugging a hole in a dilapidated boat rather than
>>> building us a nice new sleek yacht.
>> How are python's so much better?
>>
>> 1. python's ranges are exclusive of the endpoint
>>
>> 2. python doesn't have a switch statement, so case ranges being better in
>> python makes no sense
>
>
> Not every one of those has every feature you could imagine. But nice
> things about Python's slices include:
> * optional step size,
> * step size can be negative.
> * nice compact notation
> * And the a:b syntax maps to a slice object so that you can manipulate
> them and pass them around.
>
> Ruby is the only one I mentioned that has both inclusive and exclusive
> ranges (using two dots for inclusive, three dots for exclusive).
> Matlab's are always inclusive. But they all have an optional step
> size. Python's are a little annoying in that, like D, you can't use
> them outside of indexing expressions. Can't even use them in loops.
> In NumPy, the numerical library for Python, they've invented some
> quirky objects like numpy.r_ which you index to create a range
> literal. Like
> >>> numpy.r_[0:4:0.5]
> array([ 0. , 0.5, 1. , 1.5, 2. , 2.5, 3. , 3.5])
> You could do the same in D, but I don't think anyone in NumPy thinks
> of it as a particularly elegant way to make ranges (compared to matlab
> where just plain 0:4:0.5 gets you the same thing). Also you'd most
> often like to have that 4.0 in there, so you have to tweak the range
> to be [0:4.5:0.5] to get that inclusivity, because python doesn't have
> inclusive ranges. Not ideal. So they also have
>
> Anyway, you seem pretty satisfied with what you've got, so don't mind
> me. You've got to draw the line somewhere.
Nevertheless, I think these all are great ideas for additions to std.range.
Andrei
| |||
July 09, 2009 Re: Case Range Statement .. | ||||
|---|---|---|---|---|
| ||||
Posted in reply to Bill Baxter | Bill Baxter wrote:
> Not every one of those has every feature you could imagine. But nice
> things about Python's slices include:
> * optional step size,
> * step size can be negative.
> * nice compact notation
> * And the a:b syntax maps to a slice object so that you can manipulate
> them and pass them around.
Having a step size requires, of course, a third operand. This doesn't work too well with infix operator notation (the only 3 operand infix operator is ?:).
Having such a third operand, however, should mesh quite well with Andrei's range library construct.
| |||
July 09, 2009 Re: Case Range Statement .. | ||||
|---|---|---|---|---|
| ||||
Posted in reply to Andrei Alexandrescu Attachments:
| Andrei Alexandrescu wrote: > Jérôme M. Berger wrote: >> So, the correct way to define an inclusive range is with "+1" >> except when it's with "nextUp", unless you're talking about the right >> end of the range where it is inclusive by default and the right way to >> make it exclusive is with "+1" except when it's with "nextUp"? >> >> That's what I call consistent! > > I completely disagree with your assessment. First, you didn't mention what the range is supposed to do. For example, what primitives should the range have? Are you talking about a built-in type or a library-defined type? etc. > > There are two places in the language where expression1..expression2 comes into play: when slicing an array, and when iterating with foreach. In both cases the range is discrete with step 1, and so it makes sense to discuss that when expression1..expression2 is being talked about. Now you can't just silently redefine what you mean by range and then claim inconsistency. > > If you want to make a case, please state clearly what are you talking about. Nobody can be consistent with a definition that doesn't exist. > Please don't remove relevant quotations from my message. *You* were the one who said: > b+1 is correct if the range is iterated by 1, as in foreach or as an > array index. That's what Walter meant because that's what's in the > language. If you want to define a floating-point range that is closed to > the right, you may want to use an open range from a to nextUp(b). The > nextUp function (defined in std.math by Don I think) returns the very > next floating point value. That's exactly what I do in std.random. > -- mailto:jeberger@free.fr http://jeberger.free.fr Jabber: jeberger@jabber.fr | |||
July 09, 2009 Re: Case Range Statement .. | ||||
|---|---|---|---|---|
| ||||
Posted in reply to Bill Baxter Attachments:
| Bill Baxter wrote: > On Wed, Jul 8, 2009 at 4:12 PM, Andrei Alexandrescu<SeeWebsiteForEmail@erdani.org> wrote: >> Jérôme M. Berger wrote: >>> So, the correct way to define an inclusive range is with "+1" except >>> when it's with "nextUp", unless you're talking about the right end of the >>> range where it is inclusive by default and the right way to make it >>> exclusive is with "+1" except when it's with "nextUp"? >>> >>> That's what I call consistent! >> I completely disagree with your assessment. First, you didn't mention what the range is supposed to do. For example, what primitives should the range have? Are you talking about a built-in type or a library-defined type? etc. >> >> There are two places in the language where expression1..expression2 comes into play: when slicing an array, and when iterating with foreach. In both cases the range is discrete with step 1, and so it makes sense to discuss that when expression1..expression2 is being talked about. Now you can't just silently redefine what you mean by range and then claim inconsistency. >> >> If you want to make a case, please state clearly what are you talking about. Nobody can be consistent with a definition that doesn't exist. > > I think what Jerome is getting at is that we could be getting more mileage out of the xpr1..xpr2 syntax. It would be useful syntax for more than just integral, dense ranges in foreach and slices. The equivalents I've used or seen in Ruby, Python and Matlab are more versatile than D's. Perhaps that can't be translated in any useful way to a static language like D, I dunno. But it leaves one with the feeling that D's slice literals are underpowered and that the case range thing is just plugging a hole in a dilapidated boat rather than building us a nice new sleek yacht. > Exactly. Especially when I seem to remember several discussions where Walter and Andrei talked about giving D a more mathematics and scientific orientation (might be confusing with someone else though). Jerome -- mailto:jeberger@free.fr http://jeberger.free.fr Jabber: jeberger@jabber.fr | |||
July 09, 2009 Re: Case Range Statement .. | ||||
|---|---|---|---|---|
| ||||
Posted in reply to Walter Bright Attachments:
| Walter Bright wrote: > Nick Sabalausky wrote: >> "Walter Bright" <newshound1@digitalmars.com> wrote in message >>> It's handy when you want to prefix one expression to another, as in: >>> >>> (foo(), x + 3) >> >> I guess I'm not familiar with that syntax. What does that do and for what purpose? > > They're called Comma Expressions, and the left operand is evaluated first, its result discarded, then the right operand is evaluated and forms the type and result of the Comma Expression. > I've always felt they were useless and confusing. What's the advantage of "y = (foo(), x + 3);" over "foo(); y = x+3;"? > It's handy for things like rewriting ++e so it can be used more than once but is only evaluated once: > > (tmp = ++e, tmp) Uh? How is that different from "++e" Jerome -- mailto:jeberger@free.fr http://jeberger.free.fr Jabber: jeberger@jabber.fr | |||
July 09, 2009 Re: Case Range Statement .. | ||||
|---|---|---|---|---|
| ||||
Posted in reply to Walter Bright | Walter Bright:
> Having such a third operand, however, should mesh quite well with Andrei's range library construct.
In normal usage slices are sometimes useful, but slicing is mostly useful when you work with rectangular matrices, so you can slice and dice them in many ways, across axes, etc. NumPy and Matlab show such usages well. Such operations can probably be done well enough by a refined D matrix library designed for "heavy" numerical processing.
An option is to not change the current design of slices, keeping them simple, with no stride. I can accept this.
(One thing I don't like much of it is that "out of bound" slices are an hazard, you can't slice past the real size of an array. Time ago I have shown here that Python is safer in such regard, and performs something similar to: slice(a,b) === slice(max(0, min(a, $)), max(0, min(b, $))). This is quite handy (and later I have asked to Python designers, it's not a wart, it's the way they have wanted it), but it's also slower at run-time, so the current less handy behavior of D slices may be acceptable).
It's also possible to replace the current a..b syntax with something like a..b:c or a:b:c or a..b..c, etc. This is a bit more elastic than the current semantics, but not much. Even if I have asked for it in the past, I don't feel so much need for it. There are other more important features I now like to have.
If D wants to appeal to programmers that have to write numerical computations (and I think this may become one of the purposes of the D language, this means to replace some of the programs today done with Fortran and Matlab), then it may add a more general scaffold, that probably later will be used by a numeric processing library.
The Chapel language is designed for such numerical computations, among other things it has Domains, they are "index spaces". You can define arithmetic Domains, that are just one or more arithmetic ranges, open and closed, with stride (so they define an n dimensional arithmetic range, for example [0..10, 0..10] defines the space of the indexes of a 2D matrix 10x10). It allows to slice domains, to create sub-domains, un-ordered domains, associative domains and more. Then you can use them to iterate on, to initialize arrays, matrices or associative arrays defined on such Domain of indexes. It may sound complex, but I've seen it's easy to use, you can write Chapel code that uses such things only after reading about them for 20-40 minutes. Such abstraction of the idea of index space gives safety (most loops become foreach, no many out of bound situations anymore, this also means more performance because the compiler can avoid many run-time array bound checks), possibilities for the compiler to optimize and/or parallelize their usage, etc.
Bye,
bearophile
| |||
July 10, 2009 Re: Case Range Statement .. | ||||
|---|---|---|---|---|
| ||||
Posted in reply to Jérôme M. Berger | Jérôme M. Berger wrote: > Walter Bright wrote: >> Nick Sabalausky wrote: >>> "Walter Bright" <newshound1@digitalmars.com> wrote in message >>>> It's handy when you want to prefix one expression to another, as in: >>>> >>>> (foo(), x + 3) >>> >>> I guess I'm not familiar with that syntax. What does that do and for what purpose? >> >> They're called Comma Expressions, and the left operand is evaluated first, its result discarded, then the right operand is evaluated and forms the type and result of the Comma Expression. >> > I've always felt they were useless and confusing. What's the advantage of "y = (foo(), x + 3);" over "foo(); y = x+3;"? When you only see the x+3 because you're recursively walking the tree generating code. >> It's handy for things like rewriting ++e so it can be used more than once but is only evaluated once: >> >> (tmp = ++e, tmp) > > Uh? How is that different from "++e" You can then use tmp more than once with only one increment of e. | |||
Copyright © 1999-2021 by the D Language Foundation
Permalink
Reply