| Thread overview | ||||||||||
|---|---|---|---|---|---|---|---|---|---|---|
|
July 09, 2009 Enhancement request | ||||
|---|---|---|---|---|
| ||||
As D is typically a system language, this enhancement might not make it, but I still think it would be practical.
I've been thinking of a real world example for this, and yesterday found a nice example to illustrate.
Suppose you would be creating an API to interrogate a database. Now within the database, there is a table with some records. Suppose you would like to represent this table as a D class and a record as an instance of this class (or a struct, whatever).
class Person
{
uint id;
string first_name;
string last_name;
uint age;
}
Now, for the API to know how to use this class, it must most likely be inheriting some kind of interface and some mapping to actually have the member variables linked to actual columns within the table.
But it also would make the class look big and fat. So instead of that solution, might it not be better to have a way to easily get to the member names. I was thinking of a keyword in front of a type specification (class, struct, enum, etc.). For example, the keyword "reflectable". (or a pragma)
reflectable class Person
{
uint id;
string first_name;
string last_name;
uint age;
}
Now the compiler knows that it has to do some magic stuff to make the fields accessible using strings etc.
I know that it might be possible to do all of this through the vtable, classinfo, typeinfo and so on, but it doesn't appear to be very straightforward.
| ||||
July 09, 2009 Re: Enhancement request | ||||
|---|---|---|---|---|
| ||||
Posted in reply to Sjoerd van Leent | Sjoerd van Leent Wrote:
> Now the compiler knows that it has to do some magic stuff to make the fields accessible using strings etc.
>
> I know that it might be possible to do all of this through the vtable, classinfo, typeinfo and so on, but it doesn't appear to be very straightforward.
There was a request to implement this functionality in Variant.
| |||
July 09, 2009 Re: Enhancement request | ||||
|---|---|---|---|---|
| ||||
Posted in reply to Sjoerd van Leent | D2 has a getMembers method in TypeInfo and ClassInfo that would probably do the job. Only problem is that the compiler doesn't actually generate the function for it. I asked about it a while ago, but never got a response. | |||
July 09, 2009 Re: Enhancement request | ||||
|---|---|---|---|---|
| ||||
Posted in reply to Daniel Keep | Daniel Keep Wrote:
>
> D2 has a getMembers method in TypeInfo and ClassInfo that would probably do the job. Only problem is that the compiler doesn't actually generate the function for it.
>
> I asked about it a while ago, but never got a response.
I've noticed this message a while ago. I think it should be part of it. It would be practical not only for the purpose I ddescribed, but also for Network communication (RPC) and even for interoperation with embedded languages such as script languages.
I would also ask for the enhancement to provide the necessary argument information in the case of methods.
It would be the first step to some serious introspection and perhaps (later on), the ability to compile and load/modify code at runtime.
| |||
July 09, 2009 Re: Enhancement request | ||||
|---|---|---|---|---|
| ||||
Posted in reply to Sjoerd van Leent | Sjoerd van Leent wrote: > As D is typically a system language, this enhancement might not make it, but I still think it would be practical. > > I've been thinking of a real world example for this, and yesterday found a nice example to illustrate. > > Suppose you would be creating an API to interrogate a database. Now within the database, there is a table with some records. Suppose you would like to represent this table as a D class and a record as an instance of this class (or a struct, whatever). > > class Person > { > uint id; > string first_name; > string last_name; > uint age; > } > > Now, for the API to know how to use this class, it must most likely be inheriting some kind of interface and some mapping to actually have the member variables linked to actual columns within the table. > > But it also would make the class look big and fat. So instead of that solution, might it not be better to have a way to easily get to the member names. I was thinking of a keyword in front of a type specification (class, struct, enum, etc.). For example, the keyword "reflectable". (or a pragma) > > reflectable class Person > { > uint id; > string first_name; > string last_name; > uint age; > } > > Now the compiler knows that it has to do some magic stuff to make the fields accessible using strings etc. > > I know that it might be possible to do all of this through the vtable, classinfo, typeinfo and so on, but it doesn't appear to be very straightforward. http://codepad.org/1pZN2RSD Is that what you want? That gives you the types and names of all the properties of a struct/class. If you then want to interface with a database with the struct or class being automatically filled out you could use some template magic: ---- import std.string : rfind; struct Person { uint id; string first_name; string last_name; uint age; } T getFromDb(T)(string field) { // Code to get values from the database } void get( T )( ref T s ) { foreach(k, v; s.tupleof) { // Used to strip off (Person ). from the property name auto ldot = rfind( T.tupleof[k].stringof, "." ) + 1; s.tupleof[k] = getFromDb!(typeof(v)) (T.tupleof[k].stringof[ldot..$ ]); } } void main() { Person p; get( p ); // P is now populated with the values from the db } ---- | |||
July 09, 2009 Re: Enhancement request | ||||
|---|---|---|---|---|
| ||||
Posted in reply to Robert Clipsham | Robert Clipsham Wrote:
> Sjoerd van Leent wrote:
> > As D is typically a system language, this enhancement might not make it, but I still think it would be practical.
> >
> > I've been thinking of a real world example for this, and yesterday found a nice example to illustrate.
> >
> > Suppose you would be creating an API to interrogate a database. Now within the database, there is a table with some records. Suppose you would like to represent this table as a D class and a record as an instance of this class (or a struct, whatever).
> >
> > class Person
> > {
> > uint id;
> > string first_name;
> > string last_name;
> > uint age;
> > }
> >
> > Now, for the API to know how to use this class, it must most likely be inheriting some kind of interface and some mapping to actually have the member variables linked to actual columns within the table.
> >
> > But it also would make the class look big and fat. So instead of that solution, might it not be better to have a way to easily get to the member names. I was thinking of a keyword in front of a type specification (class, struct, enum, etc.). For example, the keyword "reflectable". (or a pragma)
> >
> > reflectable class Person
> > {
> > uint id;
> > string first_name;
> > string last_name;
> > uint age;
> > }
> >
> > Now the compiler knows that it has to do some magic stuff to make the fields accessible using strings etc.
> >
> > I know that it might be possible to do all of this through the vtable, classinfo, typeinfo and so on, but it doesn't appear to be very straightforward.
>
> http://codepad.org/1pZN2RSD
>
> Is that what you want? That gives you the types and names of all the properties of a struct/class. If you then want to interface with a database with the struct or class being automatically filled out you could use some template magic:
> ----
> import std.string : rfind;
>
> struct Person
> {
> uint id;
> string first_name;
> string last_name;
> uint age;
> }
>
> T getFromDb(T)(string field)
> {
> // Code to get values from the database
> }
>
> void get( T )( ref T s )
> {
> foreach(k, v; s.tupleof)
> {
> // Used to strip off (Person ). from the property name
> auto ldot = rfind( T.tupleof[k].stringof, "." ) + 1;
> s.tupleof[k] = getFromDb!(typeof(v))
> (T.tupleof[k].stringof[ldot..$ ]);
> }
> }
>
> void main()
> {
> Person p;
> get( p ); // P is now populated with the values from the db
> }
> ----
Now suppose that get() is somewhere in a library that isn't aware of object Person and of a template. Because that is the problem with libraries and especially DLL's. It needs to be more dynamic. Theoretically, it should be possible to extract everything out of Person without knowing any of the particular behavior of that class. So accessing fields, writing to fields, etc. should be possible with such libraries.
This has allways been my objection towards the heavy usage of templates. If somehow templates could be instantiated within the runtime of a program...
| |||
July 09, 2009 Re: Enhancement request | ||||
|---|---|---|---|---|
| ||||
Posted in reply to Sjoerd van Leent | Hey Robert, so how do I get all methods of a type? This doesn't work in D1.
> Now suppose that get() is somewhere in a library that isn't aware of object Person and of a template. Because that is the problem with libraries and especially DLL's. It needs to be more dynamic. Theoretically, it should be possible to extract everything out of Person without knowing any of the particular behavior of that class. So accessing fields, writing to fields, etc. should be possible with such libraries.
You still could write your own reflection library on top of tupleof. The only problem is, that you need to make all members known to that reflection library, before you can access them from any runtime context. For example, you could pass all types to a compile time function of your reflection library:
Reflection.register!(Person);
This call would instantiate template code to grab all members of Person using tupleof. That code would produce your own extended RTTI about the passed type. Then the library can map TypeInfo or ClassInfo to that extended RTTI type. You could get the RTTI information even from a DLL (as long as the runtime is shared between the DLL and the host code.)
The problem is, that you have to litter your code with calls like above. Even with D2's glorious __traits, this problem persist: you have to pass all types manually to some piece of compile time code.
Now, dear D Gods, how are we supposed to solve this problem? Could we (at least) get a way to list all members of a module with __traits? (Wow, a function crawling all modules recursively at compile time sure would produce a lot of template bloat.)
| |||
July 10, 2009 Re: Enhancement request | ||||
|---|---|---|---|---|
| ||||
Posted in reply to grauzone | grauzone Wrote: > The problem is, that you have to litter your code with calls like above. Exactly. Even though it can just be brought down to one additional statement per class, the statement in itself doesn't create any functionality, at least, from programmers perspective. This could obviously be done by a pre-compiler, but that's going to Qt way, which I don't really prefer doing, and includes the need for a complete D frontend, just to pull a few switches. > Even with D2's glorious __traits, this problem persist: you have to pass all types manually to some piece of compile time code. > > Now, dear D Gods, how are we supposed to solve this problem? Could we (at least) get a way to list all members of a module with __traits? It would, in cases that you want to have a fully reflective module (that is, being able to completely know how a module works at runtime), solve a good number of issues. > (Wow, a function crawling all modules recursively at compile time sure would produce a lot of template bloat.) I think these things are allways bloated, but at times, this is less horrible than unreadable code that doesn't have any logic except from being able to map certain things around. It would also help providing a nice interface for RPC and the like. I still have ugly memories about MSIDL and the C++ code coming from it. It's hellish, to say the least. | |||
Copyright © 1999-2021 by the D Language Foundation
Permalink
Reply