Thread overview | ||||||
---|---|---|---|---|---|---|
|
July 16, 2014 How can I express the type '(int) => int' where it is a function or a delegate | ||||
---|---|---|---|---|
| ||||
I'd like to have a Command class, where their is a name and a handler field: ```d class Command { string name; string delegate(string[]) handler; } ``` this is ok, but sometimes I want the handler also accept a function (lambdas are init to functions if no capture of outer scope variables are present), but it can't. So I'd like to generalize the Command to a template, the best I've got sofar: ```d alias string delegate(string[]) HandlerDele; alias string function(string[]) HandlerFunc; class Command(T) if (is (T HandlerDele) || is (T HandlerFunc)) { immutable { string name; T handler; } this(string name, T handler) { this.name = name; this.handler = handler; } } void main() { HandlerFunc f = xs => xs[0]; // just a test auto cmd = new Command!HandlerFunc("echo", f); } ``` I've got several questions about this: 1. I cant ignore `HandlerFunc` when initiating cmd: ```d auto cmd = new Command("echo", f); // Error: class dshell.command.Command(T) if (is(T HandlerDele) || is(T HandlerFunc)) is used as a type ``` Can DMD automatically infer the type here? 2. Is this the right way to do this? 3. I'd like a unified description of `a function pointer or a delegate`, and from the experience of lambda, it seems the syntax of lamdba is really useful here, if we have that, then instead of: ```d void execute(T)(Context cxt, T handler) if (is (T HandlerFunc) || is (T HandlerDele)) { //... } we could define a function that accepts a function/delegate like this: ```d void execute(T : string[] => string)(Context cxt, T handler) { //... } // in main ctx.execute(xs => xs[0]); |
July 16, 2014 Re: How can I express the type '(int) => int' where it is a function or a delegate | ||||
---|---|---|---|---|
| ||||
Posted in reply to Puming | On 16/07/2014 3:50 p.m., Puming wrote:
> I'd like to have a Command class, where their is a name and a handler
> field:
>
> ```d
> class Command
> {
> string name;
> string delegate(string[]) handler;
> }
> ```
>
> this is ok, but sometimes I want the handler also accept a function
> (lambdas are init to functions if no capture of outer scope variables
> are present), but it can't.
>
> So I'd like to generalize the Command to a template, the best I've got
> sofar:
>
> ```d
>
> alias string delegate(string[]) HandlerDele;
> alias string function(string[]) HandlerFunc;
>
> class Command(T) if (is (T HandlerDele) || is (T HandlerFunc))
> {
> immutable {
> string name;
> T handler;
> }
>
> this(string name, T handler)
> {
> this.name = name;
> this.handler = handler;
> }
>
> }
>
> void main()
> {
>
> HandlerFunc f = xs => xs[0]; // just a test
> auto cmd = new Command!HandlerFunc("echo", f);
> }
> ```
>
> I've got several questions about this:
>
> 1. I cant ignore `HandlerFunc` when initiating cmd:
>
> ```d
> auto cmd = new Command("echo", f); // Error: class
> dshell.command.Command(T) if (is(T HandlerDele) || is(T HandlerFunc)) is
> used as a type
> ```
>
> Can DMD automatically infer the type here?
>
> 2. Is this the right way to do this?
>
> 3. I'd like a unified description of `a function pointer or a delegate`,
> and from the experience of lambda, it seems the syntax of lamdba is
> really useful here, if we have that, then instead of:
>
> ```d
> void execute(T)(Context cxt, T handler) if (is (T HandlerFunc) || is (T
> HandlerDele))
> {
> //...
> }
>
> we could define a function that accepts a function/delegate like this:
>
> ```d
>
> void execute(T : string[] => string)(Context cxt, T handler)
> {
> //...
> }
>
> // in main
> ctx.execute(xs => xs[0]);
Or using std.functional toDelegate you could convert the function into a delegate.
class Command {
string name;
string delegate(string[]) handler;
this(string name, string delegate(string[]) handler) {
this.name = name;
this.handler = handler;
}
this(string name, string function(string[]) handler) {
import std.functional : toDelegate;
this.name = name;
this.handler = toDelegate(handler);
}
}
Just keep in mind, you can't go the opposite way.
|
July 16, 2014 Re: How can I express the type '(int) => int' where it is a function or a delegate | ||||
---|---|---|---|---|
| ||||
Posted in reply to Rikki Cattermole | On Wednesday, 16 July 2014 at 04:10:13 UTC, Rikki Cattermole wrote: > On 16/07/2014 3:50 p.m., Puming wrote: >> I'd like to have a Command class, where their is a name and a handler >> field: >> >> ```d >> class Command >> { >> string name; >> string delegate(string[]) handler; >> } >> ``` >> >> this is ok, but sometimes I want the handler also accept a function >> (lambdas are init to functions if no capture of outer scope variables >> are present), but it can't. >> >> So I'd like to generalize the Command to a template, the best I've got >> sofar: >> >> ```d >> >> alias string delegate(string[]) HandlerDele; >> alias string function(string[]) HandlerFunc; >> >> class Command(T) if (is (T HandlerDele) || is (T HandlerFunc)) >> { >> immutable { >> string name; >> T handler; >> } >> >> this(string name, T handler) >> { >> this.name = name; >> this.handler = handler; >> } >> >> } >> >> void main() >> { >> >> HandlerFunc f = xs => xs[0]; // just a test >> auto cmd = new Command!HandlerFunc("echo", f); >> } >> ``` >> >> I've got several questions about this: >> >> 1. I cant ignore `HandlerFunc` when initiating cmd: >> >> ```d >> auto cmd = new Command("echo", f); // Error: class >> dshell.command.Command(T) if (is(T HandlerDele) || is(T HandlerFunc)) is >> used as a type >> ``` >> >> Can DMD automatically infer the type here? >> >> 2. Is this the right way to do this? >> >> 3. I'd like a unified description of `a function pointer or a delegate`, >> and from the experience of lambda, it seems the syntax of lamdba is >> really useful here, if we have that, then instead of: >> >> ```d >> void execute(T)(Context cxt, T handler) if (is (T HandlerFunc) || is (T >> HandlerDele)) >> { >> //... >> } >> >> we could define a function that accepts a function/delegate like this: >> >> ```d >> >> void execute(T : string[] => string)(Context cxt, T handler) >> { >> //... >> } >> >> // in main >> ctx.execute(xs => xs[0]); > > Or using std.functional toDelegate you could convert the function into a delegate. > > class Command { > string name; > string delegate(string[]) handler; > > this(string name, string delegate(string[]) handler) { > this.name = name; > this.handler = handler; > } > > this(string name, string function(string[]) handler) { > import std.functional : toDelegate; > this.name = name; > this.handler = toDelegate(handler); > } > } > > Just keep in mind, you can't go the opposite way. Thanks. I wonder if functions could implicitly convert to delegates...but toDelegate is OK. Also, after another dig into the language docs, I found: > The .ptr property of a delegate will return the frame pointer value as a void*. > The .funcptr property of a delegate will return the function pointer value as a function type. > Future directions: Function pointers and delegates may merge into a common syntax and be interchangeable with each other. Wonder how that would happen. |
Copyright © 1999-2021 by the D Language Foundation