www.digitalmars.com         C & C++   DMDScript  

digitalmars.D.learn - Dynamic method example in TDPL

reply Joel Christensen <joelcnz gmail.com> writes:
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
next sibling parent reply Stanislav Blinov <blinov loniir.ru> writes:
  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!"
 }

Aug 20 2010
next sibling parent Andrej Mitrovic <andrej.mitrovich gmail.com> writes:
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!"
 }


Aug 20 2010
prev sibling parent Stanislav Blinov <blinov loniir.ru> writes:
  20.08.2010 15:49, Andrej Mitrovic wrote:
 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.

don't have Internet at work except for mail :|
 Btw., I haven't reached that page yet. :p

Aug 20 2010
prev sibling next sibling parent Philippe Sigaud <philippe.sigaud gmail.com> writes:
--001636c5b4e01fb633048e98970b
Content-Type: text/plain; charset=ISO-8859-1

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!"
}

--001636c5b4e01fb633048e98970b
Content-Type: text/html; charset=ISO-8859-1
Content-Transfer-Encoding: base64

U29ycnkgdG8gcmVzdXJyZWN0IGFuIG9sZCAoNCBkYXlzKSB0aHJlYWQuPGJyPkkgbW9kaWZpZWQg
dGhlIGV4YW1wbGUgYSBiaXQsIGdldHRpbmcgcmlkIG9mICYjMzk7Li4uJiMzOTsgaW4gRHluTWV0
aG9kIGFuZCBtb2RpZnlpbmcgb3BEaXNwYXRjaCBhcyBTdGFuaXNsYXYgc3VnZ2VzdGVkLiBJdCB3
b3JrcywgYW5kIGl0JiMzOTtzIGZ1biB0byBwbGF5IHdpdGg6PGJyPjxicj5tb2R1bGUgZHluYW1p
Y21ldGhvZHM7PGJyPgo8YnI+aW1wb3J0IHN0ZC5zdGRpbzs8YnI+aW1wb3J0IHN0ZC5jb252Ozxi
cj5pbXBvcnQgc3RkLnZhcmlhbnQ7PGJyPjxicj5hbGlhcyBWYXJpYW50IGRlbGVnYXRlKER5bmFt
aWMgc2VsZiwgVmFyaWFudFtdIGFyZ3MpIER5bk1ldGhvZDs8YnI+PGJyPmNsYXNzIER5bmFtaWMg
ezxicj6goKCgoKAgcHJpdmF0ZSBEeW5NZXRob2Rbc3RyaW5nXSBtZXRob2RzOzxicj6goKCgoKAg
dm9pZCBhZGRNZXRob2Qoc3RyaW5nIG5hbWUsIER5bk1ldGhvZCBtKSB7PGJyPgqgoKCgoKCgoKCg
oKCgoCBtZXRob2RzW25hbWVdID0gbTs8YnI+oKCgoKCgIH08YnI+oKCgoKCgIHZvaWQgcmVtb3Zl
TWV0aG9kKHN0cmluZyBuYW1lKSB7PGJyPqCgoKCgoKCgoKCgoKCgIG1ldGhvZHMucmVtb3ZlKG5h
bWUpOzxicj6goKCgoKAgfTxicj6goKCgoKAgLy8gRGlzcGF0Y2ggZHluYW1pY2FsbHkgb24gbWV0
aG9kPGJyPqCgoKCgoCBWYXJpYW50IGNhbGwoc3RyaW5nIG1ldGhvZE5hbWUsIFZhcmlhbnRbXSBh
cmdzKSB7PGJyPgqgoKCgoKCgoKCgoKCgoCByZXR1cm4gbWV0aG9kc1ttZXRob2ROYW1lXSh0aGlz
LCBhcmdzKTs8YnI+oKCgoKCgIH08YnI+oKCgoKCgIC8vIFByb3ZpZGUgc3ludGFjdGljIHN1Z2Fy
IHdpdGggb3BEaXNwYXRjaDxicj6goKCgoKAgVmFyaWFudCBvcERpc3BhdGNoKHN0cmluZyBtLCBB
cmdzLi4uKShBcmdzIGFyZ3MpIHs8YnI+oKCgoKCgoKCgoKCgoKAgVmFyaWFudFtdIHBhY2tlZEFy
Z3MgPSBuZXcgVmFyaWFudFthcmdzLmxlbmd0aF07PGJyPgqgoKCgoKCgoKCgoKCgoCBmb3JlYWNo
IChpLCBhcmc7IGFyZ3MpIHs8YnI+oKCgoKCgoKCgoKCgoKCgoKCgoKCgoCBwYWNrZWRBcmdzW2ld
ID0gVmFyaWFudChhcmcpOzxicj6goKCgoKCgoKCgoKCgoCB9PGJyPqCgoKCgoKCgoKCgoKCgIHJl
dHVybiBjYWxsKG0sIHBhY2tlZEFyZ3MpOzxicj6goKCgoKAgfTxicj59PGJyPjxicj52b2lkIG1h
aW4oKSB7PGJyPqCgoKCgoCBhdXRvIG9iaiA9IG5ldyBEeW5hbWljOzxicj4KoKCgoKCgIG9iai5h
ZGRNZXRob2QoJnF1b3Q7c2F5SGVsbG8mcXVvdDssPGJyPqCgoKCgoKCgoKCgoKCgIChEeW5hbWlj
LCBWYXJpYW50W10pIHs8YnI+oKCgoKCgoKCgoKCgoKCgoKCgoKCgoCB3cml0ZWxuKCZxdW90O0hl
bGxvLCB3b3JsZCEmcXVvdDspOzxicj6goKCgoKCgoKCgoKCgoKCgoKCgoKCgIHJldHVybiBWYXJp
YW50KCk7PGJyPqCgoKCgoKCgoKCgoKCgIH0pOzxicj6goKCgoKAgLy8gbSBpcyBqdXN0IHRoZSBw
cmV2aW91cyBhbm9ueW1vdXMgZGVsZWdhdGUuPGJyPgqgoKCgoKAgRHluTWV0aG9kIG0gPSAoRHlu
YW1pYywgVmFyaWFudFtdKSB7PGJyPqCgoKCgoKCgoKCgoKCgoKCgoKCgoKAgd3JpdGVsbigmcXVv
dDtIZWxsbywgd29ybGQhJnF1b3Q7KTs8YnI+oKCgoKCgoKCgoKCgoKCgoKCgoKCgoCByZXR1cm4g
VmFyaWFudCgpOzxicj6goKCgoKCgoKCgoKCgoKCgoKCgoCB9Ozxicj6goKCgoKAgb2JqLnNheUhl
bGxvKCk7IC8vIFByaW50cyAmcXVvdDtIZWxsbywgd29ybGQhJnF1b3Q7PGJyPgqgoKCgoKAgLy8g
Tm93LCB3aGF0IGFib3V0IGEgbWV0YS1tZXRob2Q/IHRlc3QgYWRkcyBhIGJ1bmNoIG9mIG1ldGhv
ZHMgaW4gb25lIGdvOjxicj6goKCgoKAgb2JqLmFkZE1ldGhvZCgmcXVvdDt0ZXN0JnF1b3Q7LDxi
cj6goKCgoKCgoKCgoKCgoKCgoKCgoCAoRHluYW1pYyBzZWxmLCBWYXJpYW50W10gYXJncykgezxi
cj6goKCgoKCgoKCgoKCgoKCgoKCgoKCgoCB3cml0ZWxuKCZxdW90O3RoZSBkeW5hbWljIGNsYXNz
IGN1cnJlbnRseSBoYXMgJnF1b3Q7LCBzZWxmLm1ldGhvZHMubGVuZ3RoLCAmcXVvdDsgbWV0aG9k
czogJnF1b3Q7LCBzZWxmLm1ldGhvZHMua2V5cyk7PGJyPgqgoKCgoKCgoKCgoKCgoKCgoKCgoKCg
oCBmb3JlYWNoKGksYXJnOyBhcmdzKSBzZWxmLmFkZE1ldGhvZCgmcXVvdDttZXRob2QmcXVvdDt+
dG8hc3RyaW5nKGkpLCBhcmcuZ2V0IUR5bk1ldGhvZCk7PGJyPqCgoKCgoKCgoKCgoKCgoKCgoKCg
oKCgIHdyaXRlbG4oJnF1b3Q7Tm93LCB0aGUgZHluYW1pYyBjbGFzcyBoYXMgJnF1b3Q7LCBzZWxm
Lm1ldGhvZHMubGVuZ3RoLCAmcXVvdDsgbWV0aG9kczogJnF1b3Q7LCBzZWxmLm1ldGhvZHMua2V5
cyk7PGJyPgqgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoCByZXR1cm4gVmFyaWFudCgpOzxicj6goKCg
oKCgoKCgoKCgoKCgoKCgoCB9KTs8YnI+oKCgoKCgoCBvYmoudGVzdChtKTsgLy8gYWRkcyBtIHRv
IG9iaiwgYXMgbWV0aG9kMDxicj6goKCgoKCgIG9iai5tZXRob2QwKCk7IC8vIHRlc3RzIGl0LiBJ
dCBwcmludHMgJnF1b3Q7SGVsbG8sIHdvcmxkISZxdW90Ozxicj59PGJyPjxicj4K
--001636c5b4e01fb633048e98970b--
Aug 24 2010
prev sibling next sibling parent Joel Christensen <joelcnz gmail.com> writes:
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
prev sibling parent Philippe Sigaud <philippe.sigaud gmail.com> writes:
--001517478f8e731901048f3880f5
Content-Type: text/plain; charset=ISO-8859-1

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. --001517478f8e731901048f3880f5 Content-Type: text/html; charset=ISO-8859-1 Content-Transfer-Encoding: quoted-printable <div class=3D"gmail_quote">On Wed, Sep 1, 2010 at 01:24, Joel Christensen <= span dir=3D"ltr">&lt;<a href=3D"mailto:joelcnz gmail.com">joelcnz gmail.com= </a>&gt;</span> wrote:<br><blockquote class=3D"gmail_quote" style=3D"margin= : 0pt 0pt 0pt 0.8ex; border-left: 1px solid rgb(204, 204, 204); padding-lef= t: 1ex;"> Thanks for the fix up Philippe.<br> <br> Just a little note. Where it says &#39;DynMethod m&#39;, you can put &#39;a= uto m&#39;, but I&#39;m wondering is it some times clearer to have the clas= s name even though &#39;auto&#39; works.<br> </blockquote></div><br>It depends on what you prefer. auto adds flexibility= : if you use auto a lot, you can change the &#39;typed&#39; parts of your c= ode and the parts with auto will likely stay the same, propagating the chan= ge without hiccup, which is well and good. But you also loose sight of what= the &#39;current&#39; type is. The compiler knows it perfectly well, thoug= h, and you can count on static typing to help you when it can.<br> <br>Personally, I&#39;m a bit leery of using auto in complex, recursive, te= mplated code: not so long ago, auto regularly created nasty forward declara= tion errors. I think some were squashed recently, but I&#39;m still testing= the water here. <br> --001517478f8e731901048f3880f5--
Sep 01 2010