www.digitalmars.com         C & C++   DMDScript  

digitalmars.D - foreach over struct, enum, class

reply Kevin Bealer <Kevin_member pathlink.com> writes:
How about iterating over structures:

myprint(double x) {...}
myprint(int x) {...}

// could be a class .. or an enum!
struct foo {
int a;
double b;
};

foo bar;

// syntax may need adjustment
foreach(alias n, bar) {
my_print(n);
}

Also, (it seems like) it should be easy to implement: you always unroll and
substitute at compile time, because struct, class, and enum are guaranteed to be
fixed size.

The above foreach would be equivalent to:

{
alias bar.a n;
my_print(n);
}
{
alias bar.b n;
my_print(n);
}

Kevin
May 06 2004
next sibling parent J Anderson <REMOVEanderson badmama.com.au> writes:
Kevin Bealer wrote:

How about iterating over structures:

myprint(double x) {...}
myprint(int x) {...}

// could be a class .. or an enum!
struct foo {
int a;
double b;
};

foo bar;

// syntax may need adjustment
foreach(alias n, bar) {
my_print(n);
}

Also, (it seems like) it should be easy to implement: you always unroll and
substitute at compile time, because struct, class, and enum are guaranteed to be
fixed size.

The above foreach would be equivalent to:

{
alias bar.a n;
my_print(n);
}
{
alias bar.b n;
my_print(n);
}

Kevin


  

This is called reflection. Many are hoping it will be included in D in one form or the another. I like this idea and have been thinking along the same lines. It would fit well with my variable arguments proposal. -- -Anderson: http://badmama.com.au/~anderson/
May 06 2004
prev sibling next sibling parent reply "Matthew" <matthew.hat stlsoft.dot.org> writes:
"Kevin Bealer" <Kevin_member pathlink.com> wrote in message
news:c7dd4m$26un$1 digitaldaemon.com...
 How about iterating over structures:

 myprint(double x) {...}
 myprint(int x) {...}

 // could be a class .. or an enum!
 struct foo {
 int a;
 double b;
 };

 foo bar;

 // syntax may need adjustment
 foreach(alias n, bar) {
 my_print(n);
 }

Sorry, I don't think that's a good idea. foreach is reserved for collections. I can't see any benefit, c/w the increased complexity and difficulty in implementing and understanding the language.
May 06 2004
parent reply Kevin Bealer <Kevin_member pathlink.com> writes:
In article <c7dlbq$2k5h$1 digitaldaemon.com>, Matthew says...
"Kevin Bealer" <Kevin_member pathlink.com> wrote in message
news:c7dd4m$26un$1 digitaldaemon.com...
 How about iterating over structures:

 myprint(double x) {...}
 myprint(int x) {...}

 // could be a class .. or an enum!
 struct foo {
 int a;
 double b;
 };

 foo bar;

 // syntax may need adjustment
 foreach(alias n, bar) {
 my_print(n);
 }

Sorry, I don't think that's a good idea. foreach is reserved for collections.

Yes. A struct is a collection.
I can't see any benefit, c/w the increased complexity and difficulty in
implementing and understanding the language.

Serialization of objects depends on this feature; you can tell, because applications that have to serialize data streams do this by hand (or with code generation, like ASN.1, XML, IReader/IWriter (in the D sample code), etc.) Most web, db, persistence, markup problems are solved with serialization. We usually view it from the other angle: datatypes "store" the data so you can build the "real" object (the XML snippet or whatever). Kevin
May 06 2004
parent reply "Matthew" <matthew.hat stlsoft.dot.org> writes:
"Kevin Bealer" <Kevin_member pathlink.com> wrote in message
news:c7do9r$2ooj$1 digitaldaemon.com...
 In article <c7dlbq$2k5h$1 digitaldaemon.com>, Matthew says...
"Kevin Bealer" <Kevin_member pathlink.com> wrote in message
news:c7dd4m$26un$1 digitaldaemon.com...
 How about iterating over structures:

 myprint(double x) {...}
 myprint(int x) {...}

 // could be a class .. or an enum!
 struct foo {
 int a;
 double b;
 };

 foo bar;

 // syntax may need adjustment
 foreach(alias n, bar) {
 my_print(n);
 }

Sorry, I don't think that's a good idea. foreach is reserved for collections.

Yes. A struct is a collection.

Well, so is an int, if you want to take it that far. Do you want to be able to freach an int for its bits?
I can't see any benefit, c/w the increased complexity and difficulty in
implementing and understanding the language.

Serialization of objects depends on this feature; you can tell, because applications that have to serialize data streams do this by hand (or with code generation, like ASN.1, XML, IReader/IWriter (in the D sample code), etc.) Most web, db, persistence, markup problems are solved with serialization. We usually view it from the other angle: datatypes "store" the data so you can build the "real" object (the XML snippet or whatever).

That's more like it. In that case, I would argue for another construct, as the confusion object is still valid.
May 06 2004
next sibling parent "Matthew" <matthew.hat stlsoft.dot.org> writes:
"Matthew" <matthew.hat stlsoft.dot.org> wrote in message
news:c7dofo$2p2a$1 digitaldaemon.com...
 "Kevin Bealer" <Kevin_member pathlink.com> wrote in message
 news:c7do9r$2ooj$1 digitaldaemon.com...
 In article <c7dlbq$2k5h$1 digitaldaemon.com>, Matthew says...
"Kevin Bealer" <Kevin_member pathlink.com> wrote in message
news:c7dd4m$26un$1 digitaldaemon.com...
 How about iterating over structures:

 myprint(double x) {...}
 myprint(int x) {...}

 // could be a class .. or an enum!
 struct foo {
 int a;
 double b;
 };

 foo bar;

 // syntax may need adjustment
 foreach(alias n, bar) {
 my_print(n);
 }

Sorry, I don't think that's a good idea. foreach is reserved for



 Yes.  A struct is a collection.

Well, so is an int, if you want to take it that far. Do you want to be able to freach an int for its bits?
I can't see any benefit, c/w the increased complexity and difficulty in
implementing and understanding the language.

Serialization of objects depends on this feature; you can tell, because applications that have to serialize data streams do this by hand (or with


 generation, like ASN.1, XML, IReader/IWriter (in the D sample code), etc.)

 Most web, db, persistence, markup problems are solved with serialization.

 We usually view it from the other angle: datatypes "store" the data so you


 build the "real" object (the XML snippet or whatever).

That's more like it. In that case, I would argue for another construct, as the confusion object is still valid.

"objection" I meant
May 06 2004
prev sibling next sibling parent Kevin Bealer <Kevin_member pathlink.com> writes:
In article <c7dofo$2p2a$1 digitaldaemon.com>, Matthew says...
"Kevin Bealer" <Kevin_member pathlink.com> wrote in message
news:c7do9r$2ooj$1 digitaldaemon.com...
 In article <c7dlbq$2k5h$1 digitaldaemon.com>, Matthew says...
"Kevin Bealer" <Kevin_member pathlink.com> wrote in message
news:c7dd4m$26un$1 digitaldaemon.com...
 How about iterating over structures:

 myprint(double x) {...}
 myprint(int x) {...}

 // could be a class .. or an enum!
 struct foo {
 int a;
 double b;
 };

 foo bar;

 // syntax may need adjustment
 foreach(alias n, bar) {
 my_print(n);
 }

Sorry, I don't think that's a good idea. foreach is reserved for collections.

Yes. A struct is a collection.

Well, so is an int, if you want to take it that far. Do you want to be able to freach an int for its bits?
I can't see any benefit, c/w the increased complexity and difficulty in
implementing and understanding the language.

Serialization of objects depends on this feature; you can tell, because applications that have to serialize data streams do this by hand (or with code generation, like ASN.1, XML, IReader/IWriter (in the D sample code), etc.) Most web, db, persistence, markup problems are solved with serialization. We usually view it from the other angle: datatypes "store" the data so you can build the "real" object (the XML snippet or whatever).

That's more like it. In that case, I would argue for another construct, as the confusion object is still valid.

Another syntax is fine with me. Maybe: struct my_quux { int x; double y; } char[] as_string(double v) {..} char[] as_string(int v) {..} for_parts(foo; bar; my_quux) { // iteration 1: foo=type alias for int, bar=object alias for x // iteration 2: foo=type alias for double, bar=object alias for y foo half = bar / 2; printf("foo size %d half value %.s\n", foo.sizeof, as_string(half)); } Better? worse? Kevin
May 06 2004
prev sibling parent Eric Anderton <Eric_member pathlink.com> writes:
 Serialization of objects depends on this feature; you can tell, because
 applications that have to serialize data streams do this by hand (or with code
 generation, like ASN.1, XML, IReader/IWriter (in the D sample code), etc.)

 Most web, db, persistence, markup problems are solved with serialization.

 We usually view it from the other angle: datatypes "store" the data so you can
 build the "real" object (the XML snippet or whatever).

That's more like it. In that case, I would argue for another construct, as the confusion object is still valid.

Since this would require a new construct for the compiler, would it be a huge stretch to go to full-on reflection instead of expanding 'foreach'? IMO, I like the elegance in using foreach in the manner suggested, but a beefed-up type/reflection system could prove more useful outside of serialization. // possible serialization with a bogus xmlWriter class. foreach(type.field f; myObj.type.fields){ xmlWriter.BeginTag("field"); xmlWriter.AddAttribute("name",f.name.toString()); xmlWriter.AddAttribute("type",f.type.toString()); xmlWriter.AddAttribute("value",f.toString()); xmlWriter.EndTag(); } // invoking a method by name void CallMethod(object myObj){ myObj.type.method["name"].call(); } // stronger debugging output?? catch(Exception e){ printf(e.toString() ~ "(caught in " ~ this.type.thismethod.name.toString() ~ ")"); }
May 06 2004
prev sibling next sibling parent reply "Walter" <newshound digitalmars.com> writes:
It's a neat way to do compile time reflection. I don't think it will serve
for runtime reflection, though (i.e. getting an arbitrary Object and
wondering what its members are without knowing the type).
May 06 2004
next sibling parent J Anderson <REMOVEanderson badmama.com.au> writes:
Walter wrote:

It's a neat way to do compile time reflection. I don't think it will serve
for runtime reflection, though (i.e. getting an arbitrary Object and
wondering what its members are without knowing the type).
  

to expose it members at runtime you could use the static method to do so. -- -Anderson: http://badmama.com.au/~anderson/
May 07 2004
prev sibling parent reply Kevin Bealer <Kevin_member pathlink.com> writes:
In article <c7fadt$24bu$1 digitaldaemon.com>, Walter says...
It's a neat way to do compile time reflection. I don't think it will serve
for runtime reflection, though (i.e. getting an arbitrary Object and
wondering what its members are without knowing the type).

I'm thinking more along the lines of compile time. For compile time, the "big" feature that all this points to, is code generation that is part of the language. In other words, routines that run at compile time, and build boilerplate code in some reasonable way. C++ programmers are trying to do this with the "pseudo functional language" of template metaprogramming, and it is a horrible mess, readability, portability and stability wise. And of course there are programs that write code based on IDLs and so on. Also, the C preprocessor is used this way: consider macros named DO_10_TIMES and DO_100_TIMES as a way of doing stone-age loops. It would be useful to have a good way to do this, in the language, to replace all the bad ways that people are doing it, NEAR the language. The fact that people are doing it in a kludgey way, tell me that the time has come for it. So essentially, I'm suggesting small programs that run at compile time, looping over lists of names and types, and building code. If it were in the same language that the code itself was in, it could be an amazing feature (maybe). I think the main reason it hasn't been done is that it opens the door to abuse (infinite loops during compile etc). But much like pointers, this is a case of trusting programmers, or not. But I suspect that it's one-revolution-too-many for the short term. Kevin
May 07 2004
next sibling parent reply J Anderson <REMOVEanderson badmama.com.au> writes:
Kevin Bealer wrote:

I'm thinking more along the lines of compile time.  For compile time, the "big"
feature that all this points to, is code generation that is part of the
language.

In other words, routines that run at compile time, and build boilerplate code in
some reasonable way.
  

but got little response. -- -Anderson: http://badmama.com.au/~anderson/
May 07 2004
parent reply "Walter" <newshound digitalmars.com> writes:
"J Anderson" <REMOVEanderson badmama.com.au> wrote in message
news:c7g8io$jbi$1 digitaldaemon.com...
 Kevin Bealer wrote:
I'm thinking more along the lines of compile time.  For compile time, the


feature that all this points to, is code generation that is part of the
language.

In other words, routines that run at compile time, and build boilerplate


some reasonable way.

but got little response.

Can you point me towards your postings on this?
May 07 2004
parent reply J Anderson <REMOVEanderson badmama.com.au> writes:
Walter wrote:

I agree.  I discussed something along compile-time-functions, ages ago
but got little response.
    

Can you point me towards your postings on this?

can give you the subject title and date, if your using a newsreader: Title: Idea - Compile Time functions Date: 9/23/2003 1:21 AM The idea changes a bit at the end of the thread. -- -Anderson: http://badmama.com.au/~anderson/
May 07 2004
parent J C Calvarese <jcc7 cox.net> writes:
J Anderson wrote:

 Walter wrote:
 
 I agree.  I discussed something along compile-time-functions, ages ago
 but got little response.
   

Can you point me towards your postings on this?

can give you the subject title and date, if your using a newsreader: Title: Idea - Compile Time functions Date: 9/23/2003 1:21 AM

Sounds like: D/17623
 
 The idea changes a bit at the end of the thread.

-- Justin (a/k/a jcc7) http://jcc_7.tripod.com/d/
May 09 2004
prev sibling next sibling parent reply "Walter" <newshound digitalmars.com> writes:
"Kevin Bealer" <Kevin_member pathlink.com> wrote in message
news:c7g6ks$g3i$1 digitaldaemon.com...
 In article <c7fadt$24bu$1 digitaldaemon.com>, Walter says...
It's a neat way to do compile time reflection. I don't think it will


for runtime reflection, though (i.e. getting an arbitrary Object and
wondering what its members are without knowing the type).

I'm thinking more along the lines of compile time. For compile time, the

 feature that all this points to, is code generation that is part of the
 language.

 In other words, routines that run at compile time, and build boilerplate

 some reasonable way.

 C++ programmers are trying to do this with the "pseudo functional

 template metaprogramming, and it is a horrible mess, readability,

 and stability wise.  And of course there are programs that write code

 IDLs and so on.  Also, the C preprocessor is used this way:  consider

 named DO_10_TIMES and DO_100_TIMES as a way of doing stone-age loops.

 It would be useful to have a good way to do this, in the language, to

 all the bad ways that people are doing it, NEAR the language.  The fact

 people are doing it in a kludgey way, tell me that the time has come for

 So essentially, I'm suggesting small programs that run at compile time,

 over lists of names and types, and building code.  If it were in the same
 language that the code itself was in, it could be an amazing feature

I think you're on the right track. I've been exchanging email with some C++ template exports who feel the same way you do.
 I think the main reason it hasn't been done is that it opens the door to

 (infinite loops during compile etc).  But much like pointers, this is a

 trusting programmers, or not.

 But I suspect that it's one-revolution-too-many for the short term.

This is probably a D 2.0 feature <g>.
May 07 2004
next sibling parent Mike Wynn <one_mad_alien hotmail.com> writes:
On Fri, 7 May 2004 13:21:55 -0700, "Walter"
<newshound digitalmars.com> wrote:

 So essentially, I'm suggesting small programs that run at compile time,

 over lists of names and types, and building code.  If it were in the same
 language that the code itself was in, it could be an amazing feature

I think you're on the right track. I've been exchanging email with some C++ template exports who feel the same way you do.

sounds like vhdl generate to me.
 I think the main reason it hasn't been done is that it opens the door to

 (infinite loops during compile etc).  But much like pointers, this is a

 trusting programmers, or not.

 But I suspect that it's one-revolution-too-many for the short term.

This is probably a D 2.0 feature <g>.

May 07 2004
prev sibling next sibling parent Kevin Bealer <Kevin_member pathlink.com> writes:
In article <c7grbl$1fho$2 digitaldaemon.com>, Walter says...
I think you're on the right track. I've been exchanging email with some C++
template exports who feel the same way you do.

I'm on the edge of my seat..
 I think the main reason it hasn't been done is that it opens the door to

 (infinite loops during compile etc).  But much like pointers, this is a

 trusting programmers, or not.

 But I suspect that it's one-revolution-too-many for the short term.

This is probably a D 2.0 feature <g>.

Just when you think it's too good to be true, it gets better. Kevin
May 07 2004
prev sibling parent reply "Walter" <newshound digitalmars.com> writes:
"Walter" <newshound digitalmars.com> wrote in message
news:c7grbl$1fho$2 digitaldaemon.com...
 I've been exchanging email with some C++
 template exports who feel the same way you do.

That should be "experts". Talk about a freudian slip! LOL
May 07 2004
parent "Phill" <phill pacific.net.au> writes:
"Walter" <newshound digitalmars.com> wrote in message
news:c7gu2p$1jna$1 digitaldaemon.com...
 "Walter" <newshound digitalmars.com> wrote in message
 news:c7grbl$1fho$2 digitaldaemon.com...
 I've been exchanging email with some C++
 template exports who feel the same way you do.

That should be "experts". Talk about a freudian slip! LOL

Well there are a few of both here arent there lol. C++ experts and C++ exports! Phill.

May 07 2004
prev sibling parent Sean Kelly <sean ffwd.cx> writes:
Kevin Bealer wrote:

 
 I'm thinking more along the lines of compile time.  For compile time, the "big"
 feature that all this points to, is code generation that is part of the
 language.
 
 In other words, routines that run at compile time, and build boilerplate code
in
 some reasonable way.
 
 C++ programmers are trying to do this with the "pseudo functional language" of
 template metaprogramming, and it is a horrible mess, readability, portability
 and stability wise.  And of course there are programs that write code based on
 IDLs and so on.  Also, the C preprocessor is used this way:  consider macros
 named DO_10_TIMES and DO_100_TIMES as a way of doing stone-age loops.
 
 It would be useful to have a good way to do this, in the language, to replace
 all the bad ways that people are doing it, NEAR the language.  The fact that
 people are doing it in a kludgey way, tell me that the time has come for it.

I agree wholeheartedly. The C++ template language may be semantically complete but it's a bear to use for code generation, which has become quite popular in the past few years. While templated typedefs will probably help quite a bit, some attention really needs to be paid to fleshing out the template language specifically for code generation. I'd love to see the same thing happen with D. Sean
May 07 2004
prev sibling parent reply Andy Friesen <andy ikagames.com> writes:
Kevin Bealer wrote:

 How about iterating over structures:
 
 myprint(double x) {...}
 myprint(int x) {...}
 
 // could be a class .. or an enum!
 struct foo {
 int a;
 double b;
 };
 
 foo bar;
 
 // syntax may need adjustment
 foreach(alias n, bar) {
 my_print(n);
 }

This opens up some really interesting possibilities, but it smells like a can of worms that may well be better left unopened. What if you only want to iterate over public attributes? Protected methods? (something that has irked me for some time now is the fact that there is no generic way to pry the individual argument types out of a delegate and put them back) Then again, the more I think of it, Walter's idea concerning type expressions* may be enough to handle it. I can't escape the notion that it would require some sort of pseudostruct to iterate over to effectively carry everything it needs to. * I forget where exactly it was that he proposed it: (int == T) ? b : c; /* b iff T is an alias for int, else c */ If D grew something like this and tuples for 2.0, the varargs problem could finally be completely, utterly solved without any need for RTTI. (you'd just foreach over a tuple whose size and composition could be known at compile time) -- andy
May 07 2004
parent J Anderson <REMOVEanderson badmama.com.au> writes:
Andy Friesen wrote:

 What if you only want to iterate over public attributes?  Protected 
 methods? (something that has irked me for some time now is the fact 
 that there is no generic way to pry the individual argument types out 
 of a delegate and put them back)

This could all be contained inside the class itself. I mean, you wouldn't be able to iterate over anything outside the class, although you could get access vir a method. Outside access could be nice but its not really required. -- -Anderson: http://badmama.com.au/~anderson/
May 07 2004