digitalmars.D.learn - Dynamic method example in TDPL
- Joel Christensen (42/43) Aug 20 2010 I've typed this example program in, but it doesn't compile. I looked up
- Stanislav Blinov (3/45) Aug 20 2010 Maybe Andrej can add this one to errata too? :)
- Andrej Mitrovic (4/55) Aug 20 2010 You mean Andrei?
- Stanislav Blinov (4/7) Aug 20 2010 Yeah, I know that. It's just that I can't do it till tomorrow, because I...
- Philippe Sigaud (58/58) Aug 24 2010 Sorry to resurrect an old (4 days) thread.
- Joel Christensen (4/4) Aug 31 2010 Thanks for the fix up Philippe.
- Philippe Sigaud (11/15) Sep 01 2010 It depends on what you prefer. auto adds flexibility: if you use auto a ...
I've typed this example program in, but it doesn't compile. I looked up the The D programming language errata but it wasn't listed. I'm using DMD v2.048./** Date: Aug 20, 2010 This was copied from TDPL book pages 386 - 387 */ module dynamicmethods; import std.stdio; import std.variant; alias Variant delegate(Dynamic self, Variant[] args...) DynMethod; class Dynamic { private DynMethod[string] methods; void addMethod(string name, DynMethod m) { methods[name] = m; } void removeMethod(string name) { methods.remove(name); } // Dispatch dynamically on method Variant call(string methodName, Variant[] args...) { return methods[methodName](this, args); } // Provide syntactic sugar with opDispatch Variant opDispatch(string m, Args)(Args args...) { Variant[] packedArgs = new Variant[args.length]; foreach (i, arg; args) { packedArgs[i] = Variant(arg); } return call(m, args); } } void main() { auto obj = new Dynamic; obj.addMethod("sayHello", Variant(Dynamic, Variant[]) { //#error here. (found '{' expecting ',' writeln("Hello, world!"); return Variant(); }); obj.sayHello(); // Prints "Hello, world!" } <<
Aug 20 2010
20.08.2010 13:00, Joel Christensen wrote: There seem to be quite a few errors in this one:/** Date: Aug 20, 2010 This was copied from TDPL book pages 386 - 387 */ module dynamicmethods; import std.stdio; import std.variant; alias Variant delegate(Dynamic self, Variant[] args...) DynMethod; class Dynamic { private DynMethod[string] methods; void addMethod(string name, DynMethod m) { methods[name] = m; } void removeMethod(string name) { methods.remove(name); } // Dispatch dynamically on method Variant call(string methodName, Variant[] args...) { return methods[methodName](this, args); } // Provide syntactic sugar with opDispatch Variant opDispatch(string m, /*was: Args*/Args...)(/*was: Args args...*/Args args) { // There should've been variadic template instead of variadic function Variant[] packedArgs = new Variant[args.length]; foreach (i, arg; args) { packedArgs[i] = Variant(arg); } return call(m, /*was: args*/packedArgs); // args was used instead of packedArgs } } void main() { auto obj = new Dynamic; obj.addMethod("sayHello", delegate Variant(Dynamic, Variant[]...) { // delegate keyword was missing, and it wasn't matching DynMethod signature writeln("Hello, world!"); return Variant(); }); obj.sayHello(); // Prints "Hello, world!" }Maybe Andrej can add this one to errata too? :)
Aug 20 2010
You mean Andrei? P.S. anyone can edit the errata page. It has a history backup, so if someone accidentally screws up something you can roll back to a previous version. If you find something that needs to be added, go ahead and do it. Btw., I haven't reached that page yet. :p Stanislav Blinov Wrote:20.08.2010 13:00, Joel Christensen wrote: There seem to be quite a few errors in this one:/** Date: Aug 20, 2010 This was copied from TDPL book pages 386 - 387 */ module dynamicmethods; import std.stdio; import std.variant; alias Variant delegate(Dynamic self, Variant[] args...) DynMethod; class Dynamic { private DynMethod[string] methods; void addMethod(string name, DynMethod m) { methods[name] = m; } void removeMethod(string name) { methods.remove(name); } // Dispatch dynamically on method Variant call(string methodName, Variant[] args...) { return methods[methodName](this, args); } // Provide syntactic sugar with opDispatch Variant opDispatch(string m, /*was: Args*/Args...)(/*was: Args args...*/Args args) { // There should've been variadic template instead of variadic function Variant[] packedArgs = new Variant[args.length]; foreach (i, arg; args) { packedArgs[i] = Variant(arg); } return call(m, /*was: args*/packedArgs); // args was used instead of packedArgs } } void main() { auto obj = new Dynamic; obj.addMethod("sayHello", delegate Variant(Dynamic, Variant[]...) { // delegate keyword was missing, and it wasn't matching DynMethod signature writeln("Hello, world!"); return Variant(); }); obj.sayHello(); // Prints "Hello, world!" }Maybe Andrej can add this one to errata too? :)
Aug 20 2010
20.08.2010 15:49, Andrej Mitrovic wrote:You mean Andrei?Nope :pP.S. anyone can edit the errata page. It has a history backup, so if someone accidentally screws up something you can roll back to a previous version. If you find something that needs to be added, go ahead and do it.Yeah, I know that. It's just that I can't do it till tomorrow, because I don't have Internet at work except for mail :|Btw., I haven't reached that page yet. :p
Aug 20 2010
Sorry to resurrect an old (4 days) thread. I modified the example a bit, getting rid of '...' in DynMethod and modifying opDispatch as Stanislav suggested. It works, and it's fun to play with: module dynamicmethods; import std.stdio; import std.conv; import std.variant; alias Variant delegate(Dynamic self, Variant[] args) DynMethod; class Dynamic { private DynMethod[string] methods; void addMethod(string name, DynMethod m) { methods[name] = m; } void removeMethod(string name) { methods.remove(name); } // Dispatch dynamically on method Variant call(string methodName, Variant[] args) { return methods[methodName](this, args); } // Provide syntactic sugar with opDispatch Variant opDispatch(string m, Args...)(Args args) { Variant[] packedArgs = new Variant[args.length]; foreach (i, arg; args) { packedArgs[i] = Variant(arg); } return call(m, packedArgs); } } void main() { auto obj = new Dynamic; obj.addMethod("sayHello", (Dynamic, Variant[]) { writeln("Hello, world!"); return Variant(); }); // m is just the previous anonymous delegate. DynMethod m = (Dynamic, Variant[]) { writeln("Hello, world!"); return Variant(); }; obj.sayHello(); // Prints "Hello, world!" // Now, what about a meta-method? test adds a bunch of methods in one go: obj.addMethod("test", (Dynamic self, Variant[] args) { writeln("the dynamic class currently has ", self.methods.length, " methods: ", self.methods.keys); foreach(i,arg; args) self.addMethod("method"~to!string(i), arg.get!DynMethod); writeln("Now, the dynamic class has ", self.methods.length, " methods: ", self.methods.keys); return Variant(); }); obj.test(m); // adds m to obj, as method0 obj.method0(); // tests it. It prints "Hello, world!" }
Aug 24 2010
Thanks for the fix up Philippe. Just a little note. Where it says 'DynMethod m', you can put 'auto m', but I'm wondering is it some times clearer to have the class name even though 'auto' works.
Aug 31 2010
On Wed, Sep 1, 2010 at 01:24, Joel Christensen <joelcnz gmail.com> wrote:Thanks for the fix up Philippe. Just a little note. Where it says 'DynMethod m', you can put 'auto m', but I'm wondering is it some times clearer to have the class name even though 'auto' works.It depends on what you prefer. auto adds flexibility: if you use auto a lot, you can change the 'typed' parts of your code and the parts with auto will likely stay the same, propagating the change without hiccup, which is well and good. But you also loose sight of what the 'current' type is. The compiler knows it perfectly well, though, and you can count on static typing to help you when it can. Personally, I'm a bit leery of using auto in complex, recursive, templated code: not so long ago, auto regularly created nasty forward declaration errors. I think some were squashed recently, but I'm still testing the water here.
Sep 01 2010