www.digitalmars.com         C & C++   DMDScript  

digitalmars.D - Events

reply "Craig Black" <cblack ara.com> writes:
An event class would contain a time stamp, a delegate/function and any 
parameters
associated with the delegate/function.

For example:

void myFunc(int i)
{
    printf("%d\n", i);
}

class MyEvent
{
    float time;
    void function(int) func;
    int i;
    void invoke() { func(i); }
}

void main(char[][] args)
{
   MyEvent event;
   event.func = &myFunc;
   event.i = 5;
   event.invoke();
}

Is there a way to describe an event generically in D so that a new class 
does not have to be created for each new function/method signature?  If not, 
perhaps D could provide a mechanism for this.

-Craig 
Feb 15 2005
next sibling parent reply "Walter" <newshound digitalmars.com> writes:
I think what you're looking for are called "delegates" in D.
Feb 15 2005
parent reply "Craig Black" <cblack ara.com> writes:
"Walter" <newshound digitalmars.com> wrote in message 
news:cuu835$1tsi$1 digitaldaemon.com...
 I think what you're looking for are called "delegates" in D.

Thanks for the reply Walter. To my knowledge delegates do not store the parameter information. This is required for a generic event mechanism. The event structure must be able to hold both the delegate and the parameters associated with the method to be invoked. -Craig
Feb 16 2005
parent reply "Walter" <newshound digitalmars.com> writes:
"Craig Black" <cblack ara.com> wrote in message
news:cv096s$v9e$1 digitaldaemon.com...
 "Walter" <newshound digitalmars.com> wrote in message
 news:cuu835$1tsi$1 digitaldaemon.com...
 I think what you're looking for are called "delegates" in D.

Thanks for the reply Walter. To my knowledge delegates do not store the parameter information. This is required for a generic event mechanism.

 event structure must be able to hold both the delegate and the parameters
 associated with the method to be invoked.

Delegates are a pair consisting of a 'this' pointer and a function address. The 'this' pointer can point to anything, including an object that contains any needed state information.
Feb 16 2005
next sibling parent reply John Reimer <brk_6502 yahoo.com> writes:
Walter wrote:
 "Craig Black" <cblack ara.com> wrote in message
 news:cv096s$v9e$1 digitaldaemon.com...
 
"Walter" <newshound digitalmars.com> wrote in message
news:cuu835$1tsi$1 digitaldaemon.com...

I think what you're looking for are called "delegates" in D.

Thanks for the reply Walter. To my knowledge delegates do not store the parameter information. This is required for a generic event mechanism.

The
event structure must be able to hold both the delegate and the parameters
associated with the method to be invoked.

Delegates are a pair consisting of a 'this' pointer and a function address. The 'this' pointer can point to anything, including an object that contains any needed state information.

How do you access object state information from within a delegate? Last I checked, you can't access the 'this' pointer from the delegate.
Feb 16 2005
parent reply "Walter" <newshound digitalmars.com> writes:
"John Reimer" <brk_6502 yahoo.com> wrote in message
news:cv0aj4$10jm$1 digitaldaemon.com...
 How do you access object state information from within a delegate?  Last
 I checked, you can't access the 'this' pointer from the delegate.

You don't access it directly, you call the delegate, just as you would a pointer to a function.
Feb 16 2005
parent reply John Reimer <brk_6502 yahoo.com> writes:
Walter wrote:
 "John Reimer" <brk_6502 yahoo.com> wrote in message
 news:cv0aj4$10jm$1 digitaldaemon.com...
 
How do you access object state information from within a delegate?  Last
I checked, you can't access the 'this' pointer from the delegate.

You don't access it directly, you call the delegate, just as you would a pointer to a function.

Yes, I've been confused about this before. I forgot that it would go against the idea of a delegate to have access to the calling objects members. Kris, you can chide me for asking this question again. - John R.
Feb 16 2005
parent reply Kris <Kris_member pathlink.com> writes:
In article <cv0u6q$1qpc$1 digitaldaemon.com>, John Reimer says...
Walter wrote:
 "John Reimer" <brk_6502 yahoo.com> wrote in message
 news:cv0aj4$10jm$1 digitaldaemon.com...
 
How do you access object state information from within a delegate?  Last
I checked, you can't access the 'this' pointer from the delegate.

You don't access it directly, you call the delegate, just as you would a pointer to a function.

Yes, I've been confused about this before. I forgot that it would go against the idea of a delegate to have access to the calling objects members. Kris, you can chide me for asking this question again.

[chanting] Pie Iesu domine, dona eis requiem. [bonk] Pie Iesu domine,... [bonk] ..dona eis requiem. [bonk] Pie Iesu domine,... [bonk] ..dona eis requiem.
Feb 16 2005
next sibling parent pragma <pragma_member pathlink.com> writes:
In article <cv0va6$1rn5$1 digitaldaemon.com>, Kris says...
[chanting]
Pie Iesu domine, dona eis requiem.
[bonk]
Pie Iesu domine,...
[bonk]
..dona eis requiem.
[bonk]
Pie Iesu domine,...
[bonk]
..dona eis requiem.

And now you must chop down the mightiest (mango) tree in the forest... ..with a *herring*! - Eric Anderton at yahoo
Feb 16 2005
prev sibling parent reply John Reimer <brk_6502 yahoo.com> writes:
Kris wrote:
 In article <cv0u6q$1qpc$1 digitaldaemon.com>, John Reimer says...
 
Walter wrote:

"John Reimer" <brk_6502 yahoo.com> wrote in message
news:cv0aj4$10jm$1 digitaldaemon.com...


How do you access object state information from within a delegate?  Last
I checked, you can't access the 'this' pointer from the delegate.

You don't access it directly, you call the delegate, just as you would a pointer to a function.

Yes, I've been confused about this before. I forgot that it would go against the idea of a delegate to have access to the calling objects members. Kris, you can chide me for asking this question again.

[chanting] Pie Iesu domine, dona eis requiem. [bonk] Pie Iesu domine,... [bonk] ..dona eis requiem. [bonk] Pie Iesu domine,... [bonk] ..dona eis requiem.

Okay... I'm not getting this (other than maybe the [bonk] part :-D ). It seems to be something from a Monty Python script.
Feb 16 2005
parent reply Kris <Kris_member pathlink.com> writes:
In article <cv10tv$1t2s$1 digitaldaemon.com>, John Reimer says...
 [chanting]
 Pie Iesu domine, dona eis requiem.
 [bonk]
 Pie Iesu domine,...
 [bonk]
 ..dona eis requiem.
 [bonk]
 Pie Iesu domine,...
 [bonk]
 ..dona eis requiem.

Okay... I'm not getting this (other than maybe the [bonk] part :-D ). It seems to be something from a Monty Python script.

Self-flagellation (with a heavy book), of the Dominican-Monk variety! Twas indeed from none other than the *Holy Grail!*
Feb 16 2005
parent John Reimer <brk_6502 yahoo.com> writes:
Kris wrote:
 In article <cv10tv$1t2s$1 digitaldaemon.com>, John Reimer says...
 
[chanting]
Pie Iesu domine, dona eis requiem.
[bonk]
Pie Iesu domine,...
[bonk]
..dona eis requiem.
[bonk]
Pie Iesu domine,...
[bonk]
..dona eis requiem.

Okay... I'm not getting this (other than maybe the [bonk] part :-D ). It seems to be something from a Monty Python script.

Self-flagellation (with a heavy book), of the Dominican-Monk variety! Twas indeed from none other than the *Holy Grail!*

:-D ... Good one!
Feb 16 2005
prev sibling parent reply "Craig Black" <cblack ara.com> writes:
 Delegates are a pair consisting of a 'this' pointer and a function 
 address.
 The 'this' pointer can point to anything, including an object that 
 contains
 any needed state information.

For member methods, the this pointer should not be overwritten. It would be possible, theoretically to hold a function pointer in a delegate structure and use the this pointer as something else, but I think it would be easier to create a class that holds a function pointer and a void pointer. However, even if we do have a pointer to hold an object that contains the parameters, this still does not solve the problem of having to write a new class for the object. Using a traditional approach, each new method or function signature requires a new data structure to be defined, as well as code that performs the invokation with the parameters in the data structure. I am seeking a way to define a GENERIC event data structure, perhaps with a template or a new language feature, that does turns all this coding into a one-liner. For example, something like, void myFunc(char[] str) { // print str to the console, however D does it } // this event will be invoked at t = 1.0, it will print "hey" to the console Event event = new Event(1.0, myFunc, "hey"); -Craig
Feb 16 2005
parent reply "Walter" <newshound digitalmars.com> writes:
"Craig Black" <cblack ara.com> wrote in message
news:cv0bps$11qb$1 digitaldaemon.com...
 However, even if we do have a pointer to hold an object that contains the
 parameters, this still does not solve the problem of having to write a new
 class for the object.  Using a traditional approach, each new method or
 function signature requires a new data structure to be defined, as well as
 code that performs the invokation with the parameters in the data

With a delegate, you only need to define what the function's input and outputs are. The 'this' part of the delegate is unspecified, and can be any class added on later.
 I am seeking a way to define a GENERIC event data structure, perhaps with

 template or a new language feature, that does turns all this coding into a
 one-liner.

 For example, something like,

 void myFunc(char[] str)
 {
    // print str to the console, however D does it
 }

 // this event will be invoked at t = 1.0, it will print "hey" to the

 Event event = new Event(1.0, myFunc, "hey");

You can do that with delegates: class Event { this(double t, void delegate(char[]) dg, char[] str); }
Feb 16 2005
parent reply "Craig Black" <cblack ara.com> writes:
 You can do that with delegates:

    class Event
    {
        this(double t, void delegate(char[]) dg, char[] str);
    }

Yes but what if the function signature changes? Then your Event class does not work and you need another Event class for the other function signature. For example: void myFunc1(char[] str) { ... } void myFunc2(int i) { ... } class Event1 { double t; void function(char[]) fun; char [] str; this(double _t, void function(char[]) _fun, char[] _str) { t = _t; fun = _fun; str = _str; } void invoke() { fun(str); } } class Event2 { double t; void function(int) fun; int i; this(double _t, void function(char[]) _fun, int _str) { t = _t; fun = _fun; i = _i; } void invoke() { fun(i); } } I suppose it would be possible to use templates somehow, but even then you would need different templates for functions/methods with different numbers of parameters. Do you see the problem? -Craig
Feb 16 2005
parent reply Chris Sauls <ibisbasenji gmail.com> writes:
You don't need multiple templates... you need templates that take a 
delegate type as their parameter.  Aka:

#
#  class Event(alias DgType) {
#    this(doublt t, DgType dg, char[] str);
#  }
#

Then you would just call for template instances for your signatures. 
Some examples:

#
#  // using the template with a two-param delegate
#  alias Event!(void delegate(int,int)) Event_ii;
#  Event_ii iievent = new Event_ii(dg);
#
#  // using the template with a one-param delegate
#  alias Event!(void delegate(char[])) Event_s;
#  Event_s event = new Event_s(dg);
#

-- Chris S

Craig Black wrote:
You can do that with delegates:

   class Event
   {
       this(double t, void delegate(char[]) dg, char[] str);
   }

Yes but what if the function signature changes? Then your Event class does not work and you need another Event class for the other function signature. For example: void myFunc1(char[] str) { ... } void myFunc2(int i) { ... } class Event1 { double t; void function(char[]) fun; char [] str; this(double _t, void function(char[]) _fun, char[] _str) { t = _t; fun = _fun; str = _str; } void invoke() { fun(str); } } class Event2 { double t; void function(int) fun; int i; this(double _t, void function(char[]) _fun, int _str) { t = _t; fun = _fun; i = _i; } void invoke() { fun(i); } } I suppose it would be possible to use templates somehow, but even then you would need different templates for functions/methods with different numbers of parameters. Do you see the problem? -Craig

Feb 16 2005
parent "Craig Black" <cblack ara.com> writes:
"Chris Sauls" <ibisbasenji gmail.com> wrote in message 
news:cv1ask$26ed$1 digitaldaemon.com...
 You don't need multiple templates... you need templates that take a 
 delegate type as their parameter.  Aka:

 #
 #  class Event(alias DgType) {
 #    this(doublt t, DgType dg, char[] str);
 #  }
 #

 Then you would just call for template instances for your signatures. Some 
 examples:

 #
 #  // using the template with a two-param delegate
 #  alias Event!(void delegate(int,int)) Event_ii;
 #  Event_ii iievent = new Event_ii(dg);
 #
 #  // using the template with a one-param delegate
 #  alias Event!(void delegate(char[])) Event_s;
 #  Event_s event = new Event_s(dg);
 #

 -- Chris S

The above implementation is not adequate. Again, the event needs to contain the delegate PLUS any associated parameters, not just the delegate itself. -Craig
Feb 18 2005
prev sibling parent reply "Ben Hinkle" <ben.hinkle gmail.com> writes:
"Craig Black" <cblack ara.com> wrote in message 
news:cuu06o$1mse$1 digitaldaemon.com...
 An event class would contain a time stamp, a delegate/function and any 
 parameters
 associated with the delegate/function.

 For example:

 void myFunc(int i)
 {
    printf("%d\n", i);
 }

 class MyEvent
 {
    float time;
    void function(int) func;
    int i;
    void invoke() { func(i); }
 }

 void main(char[][] args)
 {
   MyEvent event;
   event.func = &myFunc;
   event.i = 5;
   event.invoke();
 }

 Is there a way to describe an event generically in D so that a new class 
 does not have to be created for each new function/method signature?  If 
 not, perhaps D could provide a mechanism for this.

 -Craig

The closest D comes to a generic mechanism is probably the vararg ... syntax. That would put the type information into the _arguments array that the callee can pick apart. You could also try using templates. Remember D is strongly typed so keeping the types known at compile time will probably be easier than trying to use an generic mechanism that hides the types.
Feb 15 2005
next sibling parent "Craig Black" <cblack ara.com> writes:
 The closest D comes to a generic mechanism is probably the vararg ... 
 syntax. That would put the type information into the _arguments array that 
 the callee can pick apart. You could also try using templates. Remember D 
 is strongly typed so keeping the types known at compile time will probably 
 be easier than trying to use an generic mechanism that hides the types.

With some clever templated code, varargs just might do the trick. Good idea. Thanks.
Feb 16 2005
prev sibling parent reply "Craig Black" <cblack ara.com> writes:
Wait a minute.  In order to match varargs type information with the 
delegate, one must know the delegate's parameters' type information.  Is it 
possible to know this information at compile time or even run time?  A 
compile time check would be ideal, but is it even possible to do at run 
time?

-Craig 
Feb 16 2005
parent reply Manfred Nowak <svv1999 hotmail.com> writes:
"Craig Black" wrote: 

[...]
 Is it possible to know this information at compile time

It is clearly known at compile time. Seems you want a naked function/delegate formal parameter as well as a signature formal parameter. <example> class Event{ this( double time, delegate dg1, signature s1; delegate dg2, signature s2){ dg( s); } } // ... Event e= new Event( 1.0, &myFunc1, ( actualParm1_1, ..., actualParm1_n), &myFunc2, ( actualParm2_1, ..., actualParm2_m) ); </example> The instruction to the compiler of the formal parameters `delegate dg, signature s' would be: 1. at this position expect the reference of a delegate followed by an actual parameterList surrounded by `(' and `)' (or similar). 2. the list of types of the actual parameter list must match the list of types of the formal parameter list of the referenced delegate. -manfred
Feb 16 2005
parent reply "Craig Black" <cblack ara.com> writes:
Are you serious!?  D currently supports this syntax?
Where in the specs is the documentation for this?

-Craig 
Feb 18 2005
next sibling parent reply Manfred Nowak <svv1999 hotmail.com> writes:
"Craig Black" wrote:

[...]
 D currently supports this syntax?

No. I said "want" and "would". But to me this seems very natural. A while ago I talked of computing on signatures but didn't made it into the specs. Instead signatures are now messed up with C++-like optional parameters. This may hinder the introduction of the proposed example syntax and the completion of your task in total. -manfred
Feb 22 2005
parent Chris Sauls <ibisbasenji gmail.com> writes:
Just a random thought from a guy who just got home from work and 
probably doesn't have enough brain cells active at the moment... :)

Would it be possible to put something together using an array of TypeInfo's?

-- Chris S

Manfred Nowak wrote:
 "Craig Black" wrote:
 
 [...]
 
D currently supports this syntax?

[...] No. I said "want" and "would". But to me this seems very natural. A while ago I talked of computing on signatures but didn't made it into the specs. Instead signatures are now messed up with C++-like optional parameters. This may hinder the introduction of the proposed example syntax and the completion of your task in total. -manfred

Feb 22 2005
prev sibling parent reply Manfred Nowak <svv1999 hotmail.com> writes:
"Craig Black" <cblack ara.com> wrote:

 Are you serious!?

Thinking this over: <example> class Event{ this( double time, delegate dg1, signature s1; delegate dg2, signature s2){ dg( s); } } // ... Event e= new Event( 1.0, &myFunc1, ( actualParm1_1, ..., actualParm1_n), &myFunc2, ( actualParm2_1, ..., actualParm2_m) ); </example> I noticed, that the function the compiler uses to do its work should be made available to the user through the module std.compiler. This given the example could be rewritten: <example> private import std.compiler; class Event{ this( double time, delegate dg1, signature s1, delegate dg2, signature s2){ static assert( std.compiler.isSignatureMatch( std.compiler.theSignature( dg1), s1 ) ); dg1( s1); } } // ... Event e= new Event( 1.0, &myFunc1, ( actualParm1_1, ..., actualParm1_n), &myFunc2, ( actualParm2_1, ..., actualParm2_m) ); </example> Note that restricting the usage of allSignature function/delegate constnats and signature constants to the formal parameters of functions/delegates, static asserts and functions from std.compiler does not compromise the type safety of the language. -manfred
Feb 22 2005
parent reply "Craig Black" <cblack ara.com> writes:
Rather than adding new syntax to allow for an Event class to be defined, why 
not have event as a native type in the D language, just like function and 
delegate?  This I think would be simpler.  I can't think of any other usage 
of the signature syntax that you propose than for events.  Can you?

-Craig 
Feb 23 2005
parent reply Manfred Nowak <svv1999 hotmail.com> writes:
"Craig Black" <cblack ara.com> wrote:

[...]
 why not have event as a native type in the D language,

You are right, that setting up events as a new basic type for D would render syntactic changes useless. But to set up a new basic type for every unfulfilled problem that might arise would poison the set of basic types with another instance. To avoid this poisoning at least one of the following statements must hold: 1. it is proven that the problem can not be decomposed into smaller subproblems 2. the problem can be decomposed into smaller subproblems but it is proven that none of the solutions to the smaller subproblems is of any benefit for any problem other than the originating one. It is not a prove of no benefit to be unable to think of any problem in which a partial solution have any benefit. And you may admit, that although I am able to establish an example that shows that the solution of a decomposition _can_ be used, I would not be able to convince _everyone_ of the benefits of this usage. This might be due to the fact that the decomposition lays the roots of a whole new programming paradigma. And as you may admit further: introducing a new basic type for a language _is_ more or less undistinguishable from the introduction of a whole new pogramming paradigma. -manfred
Feb 23 2005
parent reply "Craig Black" <cblack ara.com> writes:
 You are right, that setting up events as a new basic type for D
 would render syntactic changes useless. But to set up a new basic
 type for every unfulfilled problem that might arise would poison
 the set of basic types with another instance.

Events are a generic language feature. They are commonly used for numerous purposes, notably for GUI programming. I do not think that adding an event primitive to D would at all poison the syntax. Rather, it would add richness and elegance. -Craig
Feb 24 2005
next sibling parent Georg Wrede <georg.wrede nospam.org> writes:
Craig Black wrote:
You are right, that setting up events as a new basic type for D
would render syntactic changes useless. But to set up a new basic
type for every unfulfilled problem that might arise would poison
the set of basic types with another instance.

Events are a generic language feature. They are commonly used for numerous purposes, notably for GUI programming. I do not think that adding an event primitive to D would at all poison the syntax. Rather, it would add richness and elegance.

Considering the plethora of GUI toolkits and frameworks, is it possible that the concept of Events is confined and stable enough to actually be covered with a single type in D? I'm not against the idea, it's just that so far I have a hard time imagining that we can get by with just one type.
Feb 24 2005
prev sibling parent Manfred Nowak <svv1999 hotmail.com> writes:
"Craig Black" <cblack ara.com> wrote:

[...]
 Events are a generic language feature.

You want them to become so.
 They are commonly used for numerous purposes, notably for GUI
 programming.

And which language designer already followed your proposal? And if he did not follow what was wrong with his arguments for not following?
 I do not think that adding an event primitive to D would at all
 poison the syntax.  Rather, it would add richness and elegance.

How do you measure richness or elegance against poisoning of the set of basic types? And would you admit that every other proposal with an outcome in this area that at least equals the measure your proposal reach must be also incorporated into the language D? Can it be, that the most rich and elegant language in your opinion is a language, in which solutions to every problem can be expressed by a short sequence of words, wishful only one word? I am to admit that in D the generic type of associative arrays is present for which none of the two rules holds which I specified in the former posting. If you can transfer the principles of adding this type to your proposal I am on your side. But now lay out, what the basic operations on the event type are. Given the declarartion `event e' how do you fill the storage, how do you call, compare, compute ... -manfred
Feb 24 2005