www.digitalmars.com         C & C++   DMDScript  

digitalmars.D - [suggestion] operator .. in for

reply USER <USER_member pathlink.com> writes:
#for(x=0..10){
# printf("%d\n",x);
#]


It would make coding a bit faster and easier (makes D a good language to start
to learn programming). 
Besides I don't see any dowsides.
What you think? 
Sep 07 2004
next sibling parent reply Joey Peters <Joey_member pathlink.com> writes:
In article <chl0t5$2qk9$1 digitaldaemon.com>, USER says...
#for(x=0..10){
# printf("%d\n",x);
#]


It would make coding a bit faster and easier (makes D a good language to start
to learn programming). 
Besides I don't see any dowsides.
What you think? 

I think it's horrible, it doesn't semantically make a lot of sense (also seeing how it is used for array splicing). Neither would you use that kind of thing that often. Also imagine something else used besides integers. It's a big no. You could make you own 'range' functions and then use foreach(int i; range(0, 10, 2)) for example. Or use some delegate and make an elegant function, repeat(&function, 10) or whatever.
Sep 07 2004
parent reply USER <USER_member pathlink.com> writes:
it doesn't semantically make a lot of sense


versus #for(x=0..10) Pascal has something like that: for x:=0 to 10 do ... And 0..10 means 0 to 10 It is just immitating pascal a bit. I don't want to say, we need to get rid of the old for statement, I want to add a simplier way to do this.
 Neither would you use that kind of thing that often.

#for(int x=0;x<l;x++) so why not for(x=0..l) ?? 0..l means 0 to l in array slicing, so why not everywher??
Also imagine something else used besides integers


It might seem strange to people who haven't used Pascal-like languages, but I think we can learn something from them too. They say, that Pascal is a very good language to start learning programming, because it is simple. Why not to make D a good languege to start learning too. In article <chl960$2vnd$1 digitaldaemon.com>, Joey Peters says...
In article <chl0t5$2qk9$1 digitaldaemon.com>, USER says...
#for(x=0..10){
# printf("%d\n",x);
#]


It would make coding a bit faster and easier (makes D a good language to start
to learn programming). 
Besides I don't see any dowsides.
What you think? 

I think it's horrible, it doesn't semantically make a lot of sense (also seeing how it is used for array splicing). Neither would you use that kind of thing that often. Also imagine something else used besides integers. It's a big no. You could make you own 'range' functions and then use foreach(int i; range(0, 10, 2)) for example. Or use some delegate and make an elegant function, repeat(&function, 10) or whatever.

Sep 08 2004
next sibling parent Joey Peters <Joey_member pathlink.com> writes:
In article <chmcpd$g6d$1 digitaldaemon.com>, USER says...
it doesn't semantically make a lot of sense


versus #for(x=0..10) Pascal has something like that: for x:=0 to 10 do ... And 0..10 means 0 to 10 It is just immitating pascal a bit. I don't want to say, we need to get rid of the old for statement, I want to add a simplier way to do this.

I think that at this point, it would be hard to implement this thing. Also, you/they could make some useful functions to get similar functionality. int[] range(int start, int end, int step = 1) { int[] ret; for(;start < end;start+=step) { ret.length = ret.length + 1; ret[ret.length - 1] = start; } } foreach(int x; range(0, 10)) { .. }
 Neither would you use that kind of thing that often.

#for(int x=0;x<l;x++) so why not for(x=0..l) ?? 0..l means 0 to l in array slicing, so why not everywher??

It would be grandiose confusing for the compiler. How would you do steps with that? x = 0..10..2? Also, I'm a big fan of using foreach over for loops, or when using things like x = 0 to l, you could aswell: while(x++!=l) { // problem solved } Seriously, in most languages, the times you use a for loop you're using it on an array in a for(x; x < array.length; x++) way, just an iteration, and now you can do that with foreach! The times you'd actually 'really' need it wouldn't be that a relevant reason to embed it, it's just typing a few more characters versus implementing a (relatively) hard to implement feature.
Also imagine something else used besides integers



I'd figure that when you use x = 0..10 that '..' is part of some form of an expression. The key to making useful operators is making them work in all expressions. I think they made an exception on array splicing because it's such a useful feature indeed, though they're not operators, and you're using them as operators. I figure they implemented it something like this: arrayidentifier '[' expression optsplic ']'; optsplic: | '..' expression ;
It might seem strange to people who haven't used Pascal-like languages, but I
think we can learn something from them too.

They say, that Pascal is a very good language to start learning programming,
because it is simple.
Why not to make D a good languege to start learning too.

Just because it doesn't make you type out for loops easily doesn't mean it's not a good language to start with ;)
In article <chl960$2vnd$1 digitaldaemon.com>, Joey Peters says...
In article <chl0t5$2qk9$1 digitaldaemon.com>, USER says...
#for(x=0..10){
# printf("%d\n",x);
#]


It would make coding a bit faster and easier (makes D a good language to start
to learn programming). 
Besides I don't see any dowsides.
What you think? 

I think it's horrible, it doesn't semantically make a lot of sense (also seeing how it is used for array splicing). Neither would you use that kind of thing that often. Also imagine something else used besides integers. It's a big no. You could make you own 'range' functions and then use foreach(int i; range(0, 10, 2)) for example. Or use some delegate and make an elegant function, repeat(&function, 10) or whatever.


Sep 08 2004
prev sibling next sibling parent Matthias Becker <Matthias_member pathlink.com> writes:
it doesn't semantically make a lot of sense


versus #for(x=0..10) Pascal has something like that: for x:=0 to 10 do ... And 0..10 means 0 to 10 It is just immitating pascal a bit. I don't want to say, we need to get rid of the old for statement, I want to add a simplier way to do this.
 Neither would you use that kind of thing that often.

#for(int x=0;x<l;x++) so why not for(x=0..l) ?? 0..l means 0 to l in array slicing, so why not everywher??

Could you give my an example from your code that has this kind of loop, that can't be done with foreach in an as easy way, please?
Also imagine something else used besides integers


It might seem strange to people who haven't used Pascal-like languages, but I think we can learn something from them too.

Basic-like languages have a similar but more powerfull version of what you are suggeting: FOR foo = begin TO end STEP whatever .. NEXT Step is optinal. So you don't need to and upto as in Pascal and can have other steps than 1. Anyway I don't see any use for that in D.
They say, that Pascal is a very good language to start learning programming,
because it is simple.
Why not to make D a good languege to start learning too.

Hmm, thay say the same about Python. We could learn a lot from Python, but it just won't fit into D.
Sep 08 2004
prev sibling next sibling parent Arcane Jill <Arcane_member pathlink.com> writes:
In article <chmcpd$g6d$1 digitaldaemon.com>, USER says...

0..l means 0 to l in array slicing, so why not everywher??

Actually, it doesn't. In array slicing, 0..1 means 0 to 0, not 0 to 1. Similarly, 0..10 in array slicing means elements 0 to 9. Jill
Sep 08 2004
prev sibling parent "Ivan Senji" <ivan.senji public.srce.hr> writes:
"USER" <USER_member pathlink.com> wrote in message
news:chmcpd$g6d$1 digitaldaemon.com...
it doesn't semantically make a lot of sense


versus #for(x=0..10) Pascal has something like that: for x:=0 to 10 do ... And 0..10 means 0 to 10 It is just immitating pascal a bit. I don't want to say, we need to get rid of the old for statement, I want

 a simplier way to do this.


 Neither would you use that kind of thing that often.

#for(int x=0;x<l;x++) so why not for(x=0..l) ?? 0..l means 0 to l in array slicing, so why not everywher??
Also imagine something else used besides integers



Not true, you can write your own opSlice for your class and it can have any arguments you like!
 It might seem strange to people who haven't used Pascal-like languages,

 think we can learn something from them too.

 They say, that Pascal is a very good language to start learning

 because it is simple.
 Why not to make D a good languege to start learning too.





 In article <chl960$2vnd$1 digitaldaemon.com>, Joey Peters says...
In article <chl0t5$2qk9$1 digitaldaemon.com>, USER says...
#for(x=0..10){
# printf("%d\n",x);
#]


It would make coding a bit faster and easier (makes D a good language to



to learn programming).
Besides I don't see any dowsides.
What you think?

I think it's horrible, it doesn't semantically make a lot of sense (also


how it is used for array splicing). Neither would you use that kind of


that often. Also imagine something else used besides integers. It's a big


You could make you own 'range' functions and then use foreach(int i;


10, 2)) for example. Or use some delegate and make an elegant function,
repeat(&function, 10) or whatever.


Sep 08 2004
prev sibling parent reply "Matthew" <admin stlsoft.dot.dot.dot.dot.org> writes:
DTL provides the IntegralRange template that does exactly what you need.

    foreach(int i; new IntegralRange(int)(-10, 10, 2)
    {
        printf("%d ", i);
    }

This prints

    "-10 -8 -6 -4 -2 0 2 4 6 8"

The slight uglification is the need to "new", but that's out of my hands. ;)

Check the D.dtl NG for details of where to get the latest distro.


"USER" <USER_member pathlink.com> wrote in message
news:chl0t5$2qk9$1 digitaldaemon.com...
 #for(x=0..10){
 # printf("%d\n",x);
 #]


 It would make coding a bit faster and easier (makes D a good language to start
 to learn programming).
 Besides I don't see any dowsides.
 What you think?

Sep 08 2004
next sibling parent reply Stewart Gordon <smjg_1998 yahoo.com> writes:
Matthew wrote:

 DTL provides the IntegralRange template that does exactly what you need.

Need?
     foreach(int i; new IntegralRange(int)(-10, 10, 2)

for (int i = -10; i < 10; i += 2) is not only shorter to type, it also has much less overhead. Stewart. -- My e-mail is valid but not my primary mailbox. Please keep replies on the 'group where everyone may benefit.
Sep 09 2004
next sibling parent reply Ant <Ant_member pathlink.com> writes:
In article <chppt1$29fr$1 digitaldaemon.com>, Stewart Gordon says...
Matthew wrote:

 DTL provides the IntegralRange template that does exactly what you need.

Need?
     foreach(int i; new IntegralRange(int)(-10, 10, 2)

for (int i = -10; i < 10; i += 2) is not only shorter to type, it also has much less overhead.

that's the first impression. but there must be a usefulness the IntegralRange. What can it be? anyone care to enlighten us? Ant
Sep 09 2004
parent pragma <pragma_member pathlink.com> writes:
In article <chpqhu$2a2p$1 digitaldaemon.com>, Ant says...
In article <chppt1$29fr$1 digitaldaemon.com>, Stewart Gordon says...
Matthew wrote:

 DTL provides the IntegralRange template that does exactly what you need.

Need?
     foreach(int i; new IntegralRange(int)(-10, 10, 2)

for (int i = -10; i < 10; i += 2) is not only shorter to type, it also has much less overhead.

that's the first impression. but there must be a usefulness the IntegralRange. What can it be? anyone care to enlighten us?

I'll take a stab at this one. :) How about pluggability, assuming that IntegralRange inherits from a more generic base? One could pass a range to a method, that could be virtually anything: an IntegralRange, an iterator wrapper of some kind, maybe even some kind of stream wrapper. # void doSomething(Range!(int) r){ # foreach(int i,value; r){ # writefln("range[%d] = %d",i,value); # } # } # # void main(){ # int[] list; # doSomething(new IntegralRange!(int)(-10,10,2)); // see above # doSomething(new FullRange!(int)(list)); // iterator wrapper # doSomething(new RandomRange!(int)(list)); // random, non-repeating sequence # } I'm no STL programmer, but I've always understood the advantage in generics to be that you can plug-in and substitute things all over the place. This is just another example. - Pragma [[ Eric Anderton (Sig!()) at yahoo dot com ]]
Sep 09 2004
prev sibling parent reply "Matthew" <admin.hat stlsoft.dot.org> writes:
But what about when you want to traverse a range from two arbitrary integers,
with arbitrary step? i.e. when you don't
know, a priori, whether you need a ++, --, +=, or -=?

There are other advantages, e.g. generics, to anyone caring to delve into the
subject

"Stewart Gordon" <smjg_1998 yahoo.com> wrote in message
news:chppt1$29fr$1 digitaldaemon.com...
 Matthew wrote:

 DTL provides the IntegralRange template that does exactly what you need.

Need?
     foreach(int i; new IntegralRange(int)(-10, 10, 2)

for (int i = -10; i < 10; i += 2) is not only shorter to type, it also has much less overhead. Stewart. -- My e-mail is valid but not my primary mailbox. Please keep replies on the 'group where everyone may benefit.

Sep 09 2004
parent Stewart Gordon <smjg_1998 yahoo.com> writes:
Matthew wrote:
 But what about when you want to traverse a range from two arbitrary integers,
with arbitrary step? i.e. when you don't
 know, a priori, whether you need a ++, --, +=, or -=?

Each is trivially capable of being written in terms of +=.
 There are other advantages, e.g. generics, to anyone caring to delve into the
subject

Not sure what you mean.... Stewart. -- My e-mail is valid but not my primary mailbox. Please keep replies on the 'group where everyone may benefit.
Sep 10 2004
prev sibling next sibling parent reply Sean Kelly <sean f4.ca> writes:
In article <choprh$1njb$1 digitaldaemon.com>, Matthew says...
DTL provides the IntegralRange template that does exactly what you need.

    foreach(int i; new IntegralRange(int)(-10, 10, 2)
    {
        printf("%d ", i);
    }

This prints

    "-10 -8 -6 -4 -2 0 2 4 6 8"

The slight uglification is the need to "new", but that's out of my hands. ;)

Why not offer a static opApply to generate the range? # class IntegralRange(T) # { # public: # static IntegralRange opCall( T beg, T end, T step ) # { # return new IntegralRange( beg, end, step ); # } # # this( T beg, T end, T step ) {} # } # ... # foreach(int i; IntegralRange!(int)(-10, 10, 2) ) # { # printf("%d ", i); # } Frankly, I'm half-tempted to always define static opCall constructor wrappers for classes just to simplify construction. In that vein, it might be nice for this to be legal: int x = int( 5 ); This would be a reasonable compliment to the pointer construction method: int* x = new int( 5 ); and it would allow for complete generic construction of standard types, albeit with a bit of work on the class side. Sean
Sep 09 2004
next sibling parent reply "Ben Hinkle" <bhinkle mathworks.com> writes:
Funny, I've started avoiding static opCalls. They are basically a hack. For
structs it is very easy for user code to forget to make the static opCall,
and so pretty much every member function still needs to worry about structs
with the default initialization. Also for structs it means you have to type
out the struct name twice, which is annoying. For classes saving 4
keystrokes "new " doesn't seem worth it IMO.

"Sean Kelly" <sean f4.ca> wrote in message
news:chq3uo$2f9s$1 digitaldaemon.com...
 In article <choprh$1njb$1 digitaldaemon.com>, Matthew says...
DTL provides the IntegralRange template that does exactly what you need.

    foreach(int i; new IntegralRange(int)(-10, 10, 2)
    {
        printf("%d ", i);
    }

This prints

    "-10 -8 -6 -4 -2 0 2 4 6 8"

The slight uglification is the need to "new", but that's out of my hands.


 Why not offer a static opApply to generate the range?

 # class IntegralRange(T)
 # {
 # public:
 #     static IntegralRange opCall( T beg, T end, T step )
 #     {
 #         return new IntegralRange( beg, end, step );
 #     }
 #
 #     this( T beg, T end, T step ) {}
 # }
 # ...
 # foreach(int i; IntegralRange!(int)(-10, 10, 2) )
 # {
 #     printf("%d ", i);
 # }

 Frankly, I'm half-tempted to always define static opCall constructor

 for classes just to simplify construction.  In that vein, it might be nice

 this to be legal:

 int x = int( 5 );

 This would be a reasonable compliment to the pointer construction method:

 int* x = new int( 5 );

 and it would allow for complete generic construction of standard types,

 with a bit of work on the class side.


 Sean

Sep 09 2004
next sibling parent reply Joey Peters <Joey_member pathlink.com> writes:
In article <chq4ss$2fke$1 digitaldaemon.com>, Ben Hinkle says...
Funny, I've started avoiding static opCalls. They are basically a hack. For
structs it is very easy for user code to forget to make the static opCall,
and so pretty much every member function still needs to worry about structs
with the default initialization. Also for structs it means you have to type
out the struct name twice, which is annoying. For classes saving 4
keystrokes "new " doesn't seem worth it IMO.

Hmm, nah, they make sense for things like: class Base!(RADIX) { // some base converter int opCall(char[]) { } char[] opCall(int) { } } Base!(10) dec = new Base!(10); dec(10); // "10" dec("10"); // 10 :)
Sep 09 2004
parent reply Arcane Jill <Arcane_member pathlink.com> writes:
In article <chq5gn$2g0f$1 digitaldaemon.com>, Joey Peters says...
In article <chq4ss$2fke$1 digitaldaemon.com>, Ben Hinkle says...
Funny, I've started avoiding static opCalls. They are basically a hack. For
structs it is very easy for user code to forget to make the static opCall,
and so pretty much every member function still needs to worry about structs
with the default initialization. Also for structs it means you have to type
out the struct name twice, which is annoying. For classes saving 4
keystrokes "new " doesn't seem worth it IMO.

Hmm, nah, they make sense for things like: class Base!(RADIX) { // some base converter int opCall(char[]) { } char[] opCall(int) { } } Base!(10) dec = new Base!(10); dec(10); // "10" dec("10"); // 10 :)

Joey, Ben was talking about /static/ opCall() - something of limited use. Your example is a /non-static/ opCall() - something profoundly useful. There really should be a FAQ about this distinction, as s-o m-a-n-y times we see this mistake cropping up. Arcane Jill
Sep 10 2004
parent reply Joey Peters <Joey_member pathlink.com> writes:
Joey, Ben was talking about /static/ opCall() - something of limited use.
Your example is a /non-static/ opCall() - something profoundly useful.

There really should be a FAQ about this distinction, as s-o  m-a-n-y times we
see this mistake cropping up.

Arcane Jill

D in general needs a better home, sometimes I really can't find what I'm looking for. Anyway, what 'is' the difference other than other differences with static? I could figure a use for it, like, counting references from instances of objects so you may use them anonymously (whatever you spell it, i'm not native ;)). // I so hate this newposting form, they don't do spaces class Foo { public: static Foo[uint] references; static uint cycle; uint self; this() { self = cycle; references[cycle] = this; ++cycle; } static Foo opCall(int ref) in { assert(ref >= references.length); } body { return references[ref]; } void bar() { printf("Hello :) %i\n", self); } } void anonFunction() { Foo(0).bar(); } void main() { new Foo; new Foo; anonFunction(); } I have something similar in my dragon stl, it counts spawn references in hashes which you can later cast back to their former type. There's also a selecter class so you can use delegates to select certain instances with certain properties set to value X (select LIST where DELEGATE is TRUE). But that's really out of the question now :P.
Sep 10 2004
parent reply Arcane Jill <Arcane_member pathlink.com> writes:
In article <chruhb$1ao8$1 digitaldaemon.com>, Joey Peters says...

Anyway, what 'is' the difference other than other differences with static?

Well, as I'm sure you know, non-static functions have access to a "this" pointer, and therefore have access to a "state", maintained by a class instance. static functions, on the other hand, cannot maintain a state - except by using global variables (which includes static member variables). So static opCall() can do nothing that couldn't otherwise have been done by an ordinary function. In fact, there is almost no diffence between: # class F # { # static int opCall() { /*whatever*/ } # } and # int f( /*whatever*/ } apart from the case of the function name. Both can access private variables declared in the same module. That said, many people use static opCall() to mimic a constructor (since currently structs don't have constructors). The reasoning being that the calling syntax is the same (apart from the word "new").
I could figure a use for it, like, counting references from instances of objects

Yes, that's true. However, an ordinary function could do exactly the same job. All that static opCall() gives you is a function whose name has an uppercase first letter.
// I so hate this newposting form, they don't do spaces

That's why I write code examples # like this
static Foo opCall(int ref) 
in {
assert(ref >= references.length);
}
body {
return references[ref];
}

Sure, but there are many alternatives you could have used to do the same thing, for example: # Foo getFoo(int n); // 1 # # class Foo # { # static Foo opIndex[int n]; // 2 (This is an array lookup, after all) # static Foo getReference(int n); // 3 # # // or simply # static Foo[uint] references; // 4 -- access the array directly # } Of course there's nothing "wrong" with your approach. It's just unexpected, which could be a maintainance problem for other coders.
I have something similar in my dragon stl, it counts spawn references in hashes
which you can later cast back to their former type. There's also a selecter
class so you can use delegates to select certain instances with certain
properties set to value X (select LIST where DELEGATE is TRUE).

Those sound like very good ideas, and I see absolutely nothing wrong with any of them, though I do question whether static opCall() is the most appropriate dispatch mechanism for them. When Ben said that he tended not to use static opCall() these days, a few posts back, I believe he meant that the only use he had for it previously was as a fake constructor, and that he now believes even that use to be not that useful. Arcane Jill
Sep 10 2004
parent Joey Peters <Joey_member pathlink.com> writes:
static Foo opCall(int ref) 
in {
assert(ref >= references.length);
}
body {
return references[ref];
}

Sure, but there are many alternatives you could have used to do the same thing, for example: # Foo getFoo(int n); // 1 # # class Foo # { # static Foo opIndex[int n]; // 2 (This is an array lookup, after all) # static Foo getReference(int n); // 3 # # // or simply # static Foo[uint] references; // 4 -- access the array directly # } Of course there's nothing "wrong" with your approach. It's just unexpected, which could be a maintainance problem for other coders.

I don't overload opCall yet, there is a reason for that. Though, there is also a reason to not put it in the (global) namespace as a normal function, but rather as a static function of a class (more about that later, the problem is when you start grouping instances).
I have something similar in my dragon stl, it counts spawn references in hashes
which you can later cast back to their former type. There's also a selecter
class so you can use delegates to select certain instances with certain
properties set to value X (select LIST where DELEGATE is TRUE).

Those sound like very good ideas, and I see absolutely nothing wrong with any of them, though I do question whether static opCall() is the most appropriate dispatch mechanism for them.

Not yet, I want to keep opCall for some form of a special query object, for now it is something that looks sort of hackish but correct: Foo.select.as!(Foo).by(&delegate).dragon stl arrayfunctions... select is static here, and it embeds the reference counting mechanism as a simple object, which, as you see, makes sense in an english form ;), 'as' is primarely there for if you use inheritances, that it doesn't lose it's functionality. I tried to mixin as!(Foo) so you could Foo.select.by(&...) but that just looped the compiler (for whatever reason). I'm working on a better interface though, and static opCalls might prove useful not typing out long statements such as: Fruit.select.as!(Fruit).by(&startWithP).del() // deletes fruit instances starting with P I'd imagine you sometimes want to use this 'query' more often than just once, or want them to change dynamically. So eitherway, I could make it so it does: Fruit.select(queryobject).del() and that would then again beat the sense out of a static opCall, since a non static version is embedded in select, and select itself is a static member. However, what if I want to group spawns? Imagine I'd be calling a query from a class Animal, and it would contain all <<put super large integer here>> animals in the whole planet. If I'd apply a query on that, it would iterate a gigantic list of references. So instead, I may want to make an enum, AnimalType, to further specify what I'm looking for, logically: Animals(Birds).select(queryobject).array function; And to construct them, you would have to: new Animal(birdtype, ...) In a more complex form of hash. Here, mixing in constructors would also prove useful, but I think that when I get to writing this functionality for the stl, I'd probably end up doing something like: Animal.setType(Bird); // create birds Anyway, that's not relevant for now, what is relevant is that static opCalls from a very far perspective would make some sense, and there is no real reason to destroy them from being overloadable except for teaching stupid programmers a stupid lesson (d0nt h4x0r ur c0d3).
When Ben said that he tended not to use static opCall() these days, a few posts
back, I believe he meant that the only use he had for it previously was as a
fake constructor, and that he now believes even that use to be not that useful.

as in Foo a = Foo()? I'd figure that could be useful, but like Ben said, not 'that' useful. #// Example where it would be useful #class Point { #public: # int x, int y; # this(int x_, int y_) { # x = x_; # y = y_; # } # static Point opCall(int x, int y) { # return new Point(x, y); # } #} #DrawLine(Point(5, 5), Point(10, 10));
Arcane Jill

Sep 10 2004
prev sibling parent Sean Kelly <sean f4.ca> writes:
In article <chq4ss$2fke$1 digitaldaemon.com>, Ben Hinkle says...
Funny, I've started avoiding static opCalls. They are basically a hack. For
structs it is very easy for user code to forget to make the static opCall,
and so pretty much every member function still needs to worry about structs
with the default initialization. Also for structs it means you have to type
out the struct name twice, which is annoying. For classes saving 4
keystrokes "new " doesn't seem worth it IMO.

True enough. I was mostly looking for a way to handle generic type construction without specialized wrapper functions. Of course any method that relies on user cooperation is not likely to succeed, so perhaps the static opCall trick isn't particularly useful. Still, it's better than a free function which does the same thing (which would be the C++ method). Sean
Sep 09 2004
prev sibling parent "Matthew" <admin.hat stlsoft.dot.org> writes:
"Sean Kelly" <sean f4.ca> wrote in message
news:chq3uo$2f9s$1 digitaldaemon.com...
 In article <choprh$1njb$1 digitaldaemon.com>, Matthew says...
DTL provides the IntegralRange template that does exactly what you need.

    foreach(int i; new IntegralRange(int)(-10, 10, 2)
    {
        printf("%d ", i);
    }

This prints

    "-10 -8 -6 -4 -2 0 2 4 6 8"

The slight uglification is the need to "new", but that's out of my hands. ;)

Why not offer a static opApply to generate the range? # class IntegralRange(T) # { # public: # static IntegralRange opCall( T beg, T end, T step ) # { # return new IntegralRange( beg, end, step ); # } # # this( T beg, T end, T step ) {} # } # ... # foreach(int i; IntegralRange!(int)(-10, 10, 2) ) # { # printf("%d ", i); # } Frankly, I'm half-tempted to always define static opCall constructor wrappers for classes just to simplify construction. In that vein, it might be nice for this to be legal: int x = int( 5 ); This would be a reasonable compliment to the pointer construction method: int* x = new int( 5 ); and it would allow for complete generic construction of standard types, albeit with a bit of work on the class side.

I've been toying with the idea, but I don't like the hack-nature of them. Nonetheless, it could be worth giving it a road test. I think we might see your suggestion reified in the next release of DTL. :-)
Sep 09 2004
prev sibling parent reply "Vathix" <vathixSpamFix dprogramming.com> writes:
"Matthew" <admin stlsoft.dot.dot.dot.dot.org> wrote in message
news:choprh$1njb$1 digitaldaemon.com...
 DTL provides the IntegralRange template that does exactly what you need.

     foreach(int i; new IntegralRange(int)(-10, 10, 2)
     {
         printf("%d ", i);
     }

 This prints

     "-10 -8 -6 -4 -2 0 2 4 6 8"

 The slight uglification is the need to "new", but that's out of my hands.

 Check the D.dtl NG for details of where to get the latest distro.

struct range(T, T step = 1) { private struct Foreach { T start, stop; int opApply(int delegate(inout T) dg) { int result; T val; for(val = start; val < stop; val += step) { result = dg(val); if(result) break; } return result; } } static Foreach opSlice(T start, T stop) in { assert(start <= stop); } body { Foreach fe; fe.start = start; fe.stop = stop; return fe; } } int main() { range!(int) f; foreach(int foo; f[30 .. 100]) { printf("%d\t", foo); } return 0; } I didn't need "new"... But for some reason range!(int)[30 .. 100] won't work: "struct range cannot be sliced with []".
Sep 09 2004
parent "Ben Hinkle" <bhinkle mathworks.com> writes:
"Vathix" <vathixSpamFix dprogramming.com> wrote in message
news:chq45i$2fbu$1 digitaldaemon.com...
 "Matthew" <admin stlsoft.dot.dot.dot.dot.org> wrote in message
 news:choprh$1njb$1 digitaldaemon.com...
 DTL provides the IntegralRange template that does exactly what you need.

     foreach(int i; new IntegralRange(int)(-10, 10, 2)
     {
         printf("%d ", i);
     }

 This prints

     "-10 -8 -6 -4 -2 0 2 4 6 8"

 The slight uglification is the need to "new", but that's out of my


 ;)
 Check the D.dtl NG for details of where to get the latest distro.

struct range(T, T step = 1) { private struct Foreach { T start, stop; int opApply(int delegate(inout T) dg) { int result; T val; for(val = start; val < stop; val += step) { result = dg(val); if(result) break; } return result; } } static Foreach opSlice(T start, T stop) in { assert(start <= stop); } body { Foreach fe; fe.start = start; fe.stop = stop; return fe; } } int main() { range!(int) f; foreach(int foo; f[30 .. 100]) { printf("%d\t", foo); } return 0; } I didn't need "new"... But for some reason range!(int)[30 .. 100] won't work: "struct range

 be sliced with []".

based on your code here's one using aliases to define something easier on the eyes: struct Range(T) { T begin, end, step; static Range make(T begin, T end, T step = 1) { Range res; res.begin = begin; res.end = end; res.step = step; return res; } int opApply(int delegate(inout T x) dg) { int res; for(T x = begin; x < end; x += step) { res = dg(x); if (res) break; } return res; } } // some pre-defined aliases for common range types alias Range!(byte).make range; alias Range!(short).make range; alias Range!(int).make range; alias Range!(uint).make range; alias Range!(long).make range; alias Range!(double).make range; int main() { foreach(int x; range(0,10,2)) { printf("%d\n",x); } foreach(double x; range(1.0,3.5,.5)) { printf("%g\n",x); } foreach(float x; Range!(float).make(1.0,3.5,.5)) { printf("%g\n",x); } return 0; }
Sep 09 2004