www.digitalmars.com         C & C++   DMDScript  

digitalmars.D.learn - Class Type Parameters

reply =?ISO-8859-1?Q?Hans-Eric_Gr=f6nlund?= <hasse42g gmail.com> writes:
How could I declare a class type parameter in D? I'd like to be able to do
something like this:

do_something_with_class(SomeClass);

How would I declare the do_something_with_class function?

Thank you on beforehand
Jan 17 2008
parent reply bearophile <bearophileHUGS lycos.com> writes:
Hans-Eric Grönlund:
 How could I declare a class type parameter in D? I'd like to be able to do
 something like this:
 do_something_with_class(SomeClass);
 How would I declare the do_something_with_class function?

Do you mean something like this? import std.stdio; class C1 { int i; } class C2 { float f; } void manage(TyClass)() { auto c = new TyClass; writefln(c); } void main() { manage!(C1); manage!(C2)(); } Note that manage is a templated function. D types seem almost first-class things, so you can manage them, with care. Bye, bearophile
Jan 17 2008
next sibling parent reply =?ISO-8859-1?Q?Hans-Eric_Gr=f6nlund?= <hasse42g gmail.com> writes:
Cool, not exactly what I was looking for, but I can use it to solve the problem
- a little differently than I'd expected.

Just out of curiosity: In Delphi (Object Pascal) one can assign a class type to
a variable, like so:

type 
TAClass = class
  ...
end;

TAClassClass = class of TAClass;

procedure do_something_with_class(AClass: TAClassClass);
begin
  ...
end;

Can something similar be done in D?


bearophile Wrote:

 Hans-Eric Grönlund:
 How could I declare a class type parameter in D? I'd like to be able to do
 something like this:
 do_something_with_class(SomeClass);
 How would I declare the do_something_with_class function?

Do you mean something like this? import std.stdio; class C1 { int i; } class C2 { float f; } void manage(TyClass)() { auto c = new TyClass; writefln(c); } void main() { manage!(C1); manage!(C2)(); } Note that manage is a templated function. D types seem almost first-class things, so you can manage them, with care. Bye, bearophile

Jan 17 2008
next sibling parent doob <doobnet gmail.com> writes:
Hans-Eric Grönlund wrote:
 Cool, not exactly what I was looking for, but I can use it to solve the
problem - a little differently than I'd expected.
 
 Just out of curiosity: In Delphi (Object Pascal) one can assign a class type
to a variable, like so:
 
 type 
 TAClass = class
   ...
 end;
 
 TAClassClass = class of TAClass;
 
 procedure do_something_with_class(AClass: TAClassClass);
 begin
   ...
 end;
 
 Can something similar be done in D?
 
 
 bearophile Wrote:
 
 Hans-Eric Grönlund:
 How could I declare a class type parameter in D? I'd like to be able to do
 something like this:
 do_something_with_class(SomeClass);
 How would I declare the do_something_with_class function?

import std.stdio; class C1 { int i; } class C2 { float f; } void manage(TyClass)() { auto c = new TyClass; writefln(c); } void main() { manage!(C1); manage!(C2)(); } Note that manage is a templated function. D types seem almost first-class things, so you can manage them, with care. Bye, bearophile


I think you can, look here: http://www.digitalmars.com/d/1.0/template.html under Specialization
Jan 17 2008
prev sibling parent reply "Jarrett Billingsley" <kb3ctd2 yahoo.com> writes:
"Hans-Eric Grönlund" <hasse42g gmail.com> wrote in message 
news:fmnv6b$1hi6$1 digitalmars.com...
 Cool, not exactly what I was looking for, but I can use it to solve the 
 problem - a little differently than I'd expected.

 Just out of curiosity: In Delphi (Object Pascal) one can assign a class 
 type to a variable, like so:

 type
 TAClass = class
  ...
 end;

 TAClassClass = class of TAClass;

 procedure do_something_with_class(AClass: TAClassClass);
 begin
  ...
 end;

 Can something similar be done in D?

Depends on what you want to do. Do you want to do compile-time stuff? Then templates are the way to go. Do you want to something at runtime with the class? Then RTTI is the way to go. typeid(AnyTypeReally) gets you an instance of the TypeInfo class which is automatically generated for every type in your program. Runtime introspection and stuff is currently really weak in D, since the compile-time stuff is (usually) sufficient, more expressive, and faster. "What do you want to _do_?" is probably the most important question here. Asking how to mechanically translate a piece of code from another language into D is not necessarily the best way to go about it, especially if the source language is one that not many people have experience with (Delphi is _reasonably_ popular but I doubt many people here have used it).
Jan 17 2008
parent reply =?ISO-8859-1?Q?Hans-Eric_Gr=f6nlund?= <hasse42g gmail.com> writes:
Ah, you're right. I should have been more specific. 

What I wanted to do was to imitate a ruby-method that accepts a code block,
runs it and retries n times if an exception is thrown. Like the ruby-method, I
wanted to let the user decide what type of exception to catch by giving it as
an argument. I explain it in more detail on my weblog:

http://www.hans-eric.com/2008/01/17/loop-abstractions-in-d/

For that reason, I guess the compile time solution (templates) is to prefer in
this case, although as a user of the function, I would have preferred a
non-template syntax.

Like this

retryable(SomeExceptionClass, args...);

over this

retryable(SomeExceptionClass)!(args...);


Cheers!


Jarrett Billingsley Wrote:

 "Hans-Eric Grönlund" <hasse42g gmail.com> wrote in message 
 news:fmnv6b$1hi6$1 digitalmars.com...
 Cool, not exactly what I was looking for, but I can use it to solve the 
 problem - a little differently than I'd expected.

 Just out of curiosity: In Delphi (Object Pascal) one can assign a class 
 type to a variable, like so:

 type
 TAClass = class
  ...
 end;

 TAClassClass = class of TAClass;

 procedure do_something_with_class(AClass: TAClassClass);
 begin
  ...
 end;

 Can something similar be done in D?

Depends on what you want to do. Do you want to do compile-time stuff? Then templates are the way to go. Do you want to something at runtime with the class? Then RTTI is the way to go. typeid(AnyTypeReally) gets you an instance of the TypeInfo class which is automatically generated for every type in your program. Runtime introspection and stuff is currently really weak in D, since the compile-time stuff is (usually) sufficient, more expressive, and faster. "What do you want to _do_?" is probably the most important question here. Asking how to mechanically translate a piece of code from another language into D is not necessarily the best way to go about it, especially if the source language is one that not many people have experience with (Delphi is _reasonably_ popular but I doubt many people here have used it).

Jan 21 2008
parent reply =?ISO-8859-1?Q?Hans-Eric_Gr=f6nlund?= <hasse42g gmail.com> writes:
 retryable(SomeExceptionClass)!(args...);

I of course meant retryable!(SomeExceptionClass)(args...); Hans-Eric Grönlund Wrote:
 Ah, you're right. I should have been more specific. 
 
 What I wanted to do was to imitate a ruby-method that accepts a code block,
runs it and retries n times if an exception is thrown. Like the ruby-method, I
wanted to let the user decide what type of exception to catch by giving it as
an argument. I explain it in more detail on my weblog:
 
 http://www.hans-eric.com/2008/01/17/loop-abstractions-in-d/
 
 For that reason, I guess the compile time solution (templates) is to prefer in
this case, although as a user of the function, I would have preferred a
non-template syntax.
 
 Like this
 
 retryable(SomeExceptionClass, args...);
 
 over this
 
 retryable(SomeExceptionClass)!(args...);
 
 
 Cheers!
 
 
 Jarrett Billingsley Wrote:
 
 "Hans-Eric Grönlund" <hasse42g gmail.com> wrote in message 
 news:fmnv6b$1hi6$1 digitalmars.com...
 Cool, not exactly what I was looking for, but I can use it to solve the 
 problem - a little differently than I'd expected.

 Just out of curiosity: In Delphi (Object Pascal) one can assign a class 
 type to a variable, like so:

 type
 TAClass = class
  ...
 end;

 TAClassClass = class of TAClass;

 procedure do_something_with_class(AClass: TAClassClass);
 begin
  ...
 end;

 Can something similar be done in D?

Depends on what you want to do. Do you want to do compile-time stuff? Then templates are the way to go. Do you want to something at runtime with the class? Then RTTI is the way to go. typeid(AnyTypeReally) gets you an instance of the TypeInfo class which is automatically generated for every type in your program. Runtime introspection and stuff is currently really weak in D, since the compile-time stuff is (usually) sufficient, more expressive, and faster. "What do you want to _do_?" is probably the most important question here. Asking how to mechanically translate a piece of code from another language into D is not necessarily the best way to go about it, especially if the source language is one that not many people have experience with (Delphi is _reasonably_ popular but I doubt many people here have used it).


Jan 21 2008
parent reply Christopher Wright <dhasenan gmail.com> writes:
Hans-Eric Grönlund wrote:
 retryable(SomeExceptionClass)!(args...);

I of course meant retryable!(SomeExceptionClass)(args...); Hans-Eric Grönlund Wrote:
 Ah, you're right. I should have been more specific. 

 What I wanted to do was to imitate a ruby-method that accepts a code block,
runs it and retries n times if an exception is thrown. Like the ruby-method, I
wanted to let the user decide what type of exception to catch by giving it as
an argument. I explain it in more detail on my weblog:

 http://www.hans-eric.com/2008/01/17/loop-abstractions-in-d/

 For that reason, I guess the compile time solution (templates) is to prefer in
this case, although as a user of the function, I would have preferred a
non-template syntax.

 Like this

 retryable(SomeExceptionClass, args...);

 over this

 retryable(SomeExceptionClass)!(args...);


 Cheers!


Closest you could come, if you really didn't want to use a template, is: void retryable(ClassInfo info, int times, void delegate() totry) { for (int i = 0; i < times; i++) { try { totry(); break; } catch (Exception e) { if (e.classinfo is info) continue; else throw e; } } } retryable(AbandonedMutexException.classinfo, 5, {writefln("Hi!");}); Typeid wouldn't work; it goes by the declared type, IIRC.
Jan 21 2008
parent reply "Jarrett Billingsley" <kb3ctd2 yahoo.com> writes:
"Christopher Wright" <dhasenan gmail.com> wrote in message 
news:fn2bqa$25rl$1 digitalmars.com...
 Closest you could come, if you really didn't want to use a template, is:
 void retryable(ClassInfo info, int times, void delegate() totry) {
    for (int i = 0; i < times; i++) {
        try {
           totry();
           break;
        } catch (Exception e) {
           if (e.classinfo is info) continue; else throw e;
        }
    }
 }

 retryable(AbandonedMutexException.classinfo, 5, {writefln("Hi!");});

The only possible issue I could see with that would be if an exception were thrown that was derived from the type that you passed in, which, according to normal exception behavior, should still be caught. What you have to do then is perform a dynamic cast. There's no syntax for this, but you can hack around with some of the runtime functions to do the same thing. Place: extern(C) Object _d_dynamic_cast(Object o, ClassInfo c); somewhere in your module, then in the catch clause of retryable: catch(Exception e) { if(_d_dynamic_cast(e, info)) continue; else throw e; } That _should_ work. It's doing the same thing as the cast operator would but without the pretty syntax. Also, this function would be a great place to use a lazy void parameter for the toTry parameter ;)
Jan 21 2008
next sibling parent "Jarrett Billingsley" <kb3ctd2 yahoo.com> writes:
"naryl" <cy ngs.ru> wrote in message news:op.t5auwulcqr3u58 iriwka...
 On Mon, 21 Jan 2008 18:57:34 +0300, Jarrett Billingsley 
 <kb3ctd2 yahoo.com> wrote:
     if(_d_dynamic_cast(e, info))
         continue;
     else
         throw e;

Isn't _d_dynamic_cast implementation specific?

Probably. :\ But it at least exists in both phobos and Tango.
Jan 21 2008
prev sibling parent reply =?ISO-8859-1?Q?Hans-Eric_Gr=f6nlund?= <hasse42g gmail.com> writes:
 Also, this function would be a great place to use a lazy void parameter for 
 the toTry parameter ;) 

Pardon me for being ignorant, but could you elaborate a little on this subject? Jarrett Billingsley Wrote:
 "Christopher Wright" <dhasenan gmail.com> wrote in message 
 news:fn2bqa$25rl$1 digitalmars.com...
 Closest you could come, if you really didn't want to use a template, is:
 void retryable(ClassInfo info, int times, void delegate() totry) {
    for (int i = 0; i < times; i++) {
        try {
           totry();
           break;
        } catch (Exception e) {
           if (e.classinfo is info) continue; else throw e;
        }
    }
 }

 retryable(AbandonedMutexException.classinfo, 5, {writefln("Hi!");});

The only possible issue I could see with that would be if an exception were thrown that was derived from the type that you passed in, which, according to normal exception behavior, should still be caught. What you have to do then is perform a dynamic cast. There's no syntax for this, but you can hack around with some of the runtime functions to do the same thing. Place: extern(C) Object _d_dynamic_cast(Object o, ClassInfo c); somewhere in your module, then in the catch clause of retryable: catch(Exception e) { if(_d_dynamic_cast(e, info)) continue; else throw e; } That _should_ work. It's doing the same thing as the cast operator would but without the pretty syntax. Also, this function would be a great place to use a lazy void parameter for the toTry parameter ;)

Jan 23 2008
parent "Jarrett Billingsley" <kb3ctd2 yahoo.com> writes:
"Hans-Eric Grönlund" <hasse42g gmail.com> wrote in message 
news:fn9csm$109r$1 digitalmars.com...
 Also, this function would be a great place to use a lazy void parameter 
 for
 the toTry parameter ;)

Pardon me for being ignorant, but could you elaborate a little on this subject?

:D void retryable(ClassInfo info, int times, lazy void totry) { for(int i = 0; i < times; i++) { try { totry(); break; } catch(Exception e) { if(_d_dynamic_cast(e, info)) continue; else throw e; } } } Notice that the body of the function has not changed, we still call totry as a function. Lazy parameters are sort of syntactic sugar. You put "lazy T" on a parameter, it is implicitly a "T delegate()". The magic happens when the function is actually called. With the old version that took a delegate, we had to write: retryable(typeid(Exception), 5, { connectToDB(); }); But lazy parameters allow us to use a normal-looking expression there: retryable(typeid(Exception), 5, connectToDB()); The compiler sees that that's a lazy parameter and implicitly converts it to a delegate literal with that code in it. If you want to have more code in the lazy parameter, it gets a bit tricky: retryable(typeid(Exception), 5, { func1(); func2(); func3(); }()); // <<< notice extra set of parens here! The reason we have to have that extra set of parens is that the compiler will wrap this in another delegate literal, leaving us (internally) with something like: void __temp1() { { func1(); func2(); func3(); }(); } If we don't put the call at the end of the delegate literal, your lazy parameter just defines a function and does nothing else.
Jan 24 2008
prev sibling parent naryl <cy ngs.ru> writes:
On Mon, 21 Jan 2008 18:57:34 +0300, Jarrett Billingsley  
<kb3ctd2 yahoo.com> wrote:
     if(_d_dynamic_cast(e, info))
         continue;
     else
         throw e;

Isn't _d_dynamic_cast implementation specific?
Jan 21 2008