digitalmars.D.announce - A library similar to boost::bind
- Tom S (50/50) Jun 18 2006 Hey there :)
- Lutger (10/60) Jul 07 2006 I'm a little late, but thanks!!! I was hoping somebody would do this. It...
- Tom S (46/57) Jul 07 2006 Thanks for testing and kind words :)
- Kirk McDonald (18/101) Jul 07 2006 I've started to write something similar for Pyd, but yours seems more
- Tom S (9/25) Jul 07 2006 Ah, I've got it in the Bind module, called 'getFuncArgsTypes'. A simple
- Lutger (6/63) Jul 07 2006 Oh joy, this is great! Imho something like this would be nice in Phobos.
- Ivan Senji (3/21) Jul 07 2006 Wow! Great peace of code, I really learned a lot from it :)
Hey there :) I've created a template lib similar to boost::bind (http://www.boost.org/libs/bind/bind.html) Grab it here: http://158.75.59.9/~h3/code/bind.rar Basically, it allows the coder to create 'bound' functions, with some of their args fixed, but also other fancy stuff. Examples: void foo(int a, int b) {} // create a function out of foo with the second argument fixed to 4 auto b1 = bind(&foo, Arg0, 4); b1(3); // calls foo(3, 4) // create a function out of foo with reversed args auto b2 = bind(&foo, Arg1, Arg0); b2(1, 2); // calls foo(2, 1) // create a function out of foo with both args fixed auto b3 = bind(&foo, 5, 6); b3(); // calls foo(5, 6) It can also be used for function compositing, like: int bar(int a, int b) { return a + b; } auto b4 = bind(&foo, bind(&bar, Arg0, Arg1), Arg2); b4(1, 2, 3); // calls foo(bar(1, 2), 3) auto b5 = bind(&foo, bind(&bar, Arg0, Arg0), Arg0); b5(1); // calls foo(bar(1, 1), 1) If a function is declared to take different types that are then bound to a single param type, automatic type negotiation is done: void func(int a, float b) {} auto b6 = bind(&func, Arg0, Arg0); b6(123); // ok, b6 expects an int Basically, out of all types for wich Arg[n] is to be used, the one is found that can be casted to all other An additional feature of the library is an ability to expand tuples, e.g. Tuple!(int, float) func2() { return makeTuple(1, 2.2f); } auto b7 = bind(&func, bind(&func2)); b7(); // calls func(1, 2.2f) Although func expects two arguments and func2 returns just one, func2 returns a Tuple composed of types that match 'func' so it's expanded/decomposed to allow such a nesting The 'bind' function returns an object with an overloaded opCall method. You can grab a delegate from it by calling .ptr() instead. More examples can be found in the archive There's a problem with the library though. It only seems to work on the windows version of DMD. When compiled on linux, DMD segfaults without providing any reasonable error message :( What could also be improved upon, are error messages in case when some types don't match Anyway, all constructive feedback is welcome. If you have any feature suggestions or bug reports, I'd be glad to hear them -- Tomasz Stachowiak /+ a.k.a. h3r3tic +/
Jun 18 2006
I'm a little late, but thanks!!! I was hoping somebody would do this. It works like a charm. I tried studying the source, and while it's a LOT better to follow than boost, I discovered I don't understand metaprogramming at all (yet), unfortunatly. Can I ask you, how can I use the Tuple type and what are it's features? This much I figured out: Tuple!(int,int) someTuple; someTuple.val!(1) = 5; assert(someTuple.val!(1) == 5); In article <e74hrn$1eo5$1 digitaldaemon.com>, Tom S says...Hey there :) I've created a template lib similar to boost::bind (http://www.boost.org/libs/bind/bind.html) Grab it here: http://158.75.59.9/~h3/code/bind.rar Basically, it allows the coder to create 'bound' functions, with some of their args fixed, but also other fancy stuff. Examples: void foo(int a, int b) {} // create a function out of foo with the second argument fixed to 4 auto b1 = bind(&foo, Arg0, 4); b1(3); // calls foo(3, 4) // create a function out of foo with reversed args auto b2 = bind(&foo, Arg1, Arg0); b2(1, 2); // calls foo(2, 1) // create a function out of foo with both args fixed auto b3 = bind(&foo, 5, 6); b3(); // calls foo(5, 6) It can also be used for function compositing, like: int bar(int a, int b) { return a + b; } auto b4 = bind(&foo, bind(&bar, Arg0, Arg1), Arg2); b4(1, 2, 3); // calls foo(bar(1, 2), 3) auto b5 = bind(&foo, bind(&bar, Arg0, Arg0), Arg0); b5(1); // calls foo(bar(1, 1), 1) If a function is declared to take different types that are then bound to a single param type, automatic type negotiation is done: void func(int a, float b) {} auto b6 = bind(&func, Arg0, Arg0); b6(123); // ok, b6 expects an int Basically, out of all types for wich Arg[n] is to be used, the one is found that can be casted to all other An additional feature of the library is an ability to expand tuples, e.g. Tuple!(int, float) func2() { return makeTuple(1, 2.2f); } auto b7 = bind(&func, bind(&func2)); b7(); // calls func(1, 2.2f) Although func expects two arguments and func2 returns just one, func2 returns a Tuple composed of types that match 'func' so it's expanded/decomposed to allow such a nesting The 'bind' function returns an object with an overloaded opCall method. You can grab a delegate from it by calling .ptr() instead. More examples can be found in the archive There's a problem with the library though. It only seems to work on the windows version of DMD. When compiled on linux, DMD segfaults without providing any reasonable error message :( What could also be improved upon, are error messages in case when some types don't match Anyway, all constructive feedback is welcome. If you have any feature suggestions or bug reports, I'd be glad to hear them -- Tomasz Stachowiak /+ a.k.a. h3r3tic +/
Jul 07 2006
Lutger wrote:I'm a little late, but thanks!!! I was hoping somebody would do this. It works like a charm. I tried studying the source, and while it's a LOT better to follow than boost, I discovered I don't understand metaprogramming at all (yet), unfortunatly. Can I ask you, how can I use the Tuple type and what are it's features? This much I figured out: Tuple!(int,int) someTuple; someTuple.val!(1) = 5; assert(someTuple.val!(1) == 5);Thanks for testing and kind words :) I've uploaded an updated version at the same address: http://158.75.59.9/~h3/code/bind.rar As for the Tuple's features, it's really pretty basic, but at the same time quite powerful and allowing for the creation of many interesting templates. I'll use an example to demonstrate its features: Tuple!(int, float) a; a.val!(0) = 5; a.val!(1) = 2.3f; // simple printing writefln(a.toString); // various insertion ops auto b = a.prepend!(char[])("foo"); writefln(b.toString); auto c = b.append!(double)(1.234567); writefln(c.toString); auto d = c.insertAfter!(1, int)(1234); writefln(d.toString); // .length property like in arrays writefln("d.length: ", d.length); // behaves like a struct auto e = d.insertBefore!(1, char[])("another string..."); auto f = e; f.val!(1) = "modified !"; writefln(e.toString); writefln(f.toString); // direct access to fields. the '.val' is an templated alias, not an accessor function f.val!(3) += 2; writefln(typeid(typeof(f.val!(3)))); writefln(f.toString); struct Test { int x; float y; double z; char w; } // no extra costs static assert(Test.sizeof == (Tuple!(int, float, double, char)).sizeof); // easy creation. // "".dup is used because we don't like static arrays. writefln(makeTuple(1, 2.2, 5.f, "foo".dup, 2+7i, "bar".dup).toString); // nest 'em as you like writefln(makeTuple(makeTuple(1, 2), makeTuple(3, 4)).toString); -- Tomasz Stachowiak /+ a.k.a. h3r3tic +/
Jul 07 2006
Tom S wrote:Lutger wrote:I've started to write something similar for Pyd, but yours seems more full-featured. One useful function of mine is a tuple_from_fn template, which derives a tuple type directly from a function type, e.g.: void func(int i, char[] s) { } void main() { tuple_from_fn!(typeof(&func)) f; static assert(is(typeof(f) == tuple!(int, char[]))); } The closest thing my tuples have to "bind" is a simple "apply_tuple_to_fn" function that calls the function with the tuple. The one question I have is: How well does it handle default function arguments? So far I've managed to support them pretty well in Pyd, and I don't want to break that. -- Kirk McDonald Pyd: Wrapping Python with D http://dsource.org/projects/pyd/wikiI'm a little late, but thanks!!! I was hoping somebody would do this. It works like a charm. I tried studying the source, and while it's a LOT better to follow than boost, I discovered I don't understand metaprogramming at all (yet), unfortunatly. Can I ask you, how can I use the Tuple type and what are it's features? This much I figured out: Tuple!(int,int) someTuple; someTuple.val!(1) = 5; assert(someTuple.val!(1) == 5);Thanks for testing and kind words :) I've uploaded an updated version at the same address: http://158.75.59.9/~h3/code/bind.rar As for the Tuple's features, it's really pretty basic, but at the same time quite powerful and allowing for the creation of many interesting templates. I'll use an example to demonstrate its features: Tuple!(int, float) a; a.val!(0) = 5; a.val!(1) = 2.3f; // simple printing writefln(a.toString); // various insertion ops auto b = a.prepend!(char[])("foo"); writefln(b.toString); auto c = b.append!(double)(1.234567); writefln(c.toString); auto d = c.insertAfter!(1, int)(1234); writefln(d.toString); // .length property like in arrays writefln("d.length: ", d.length); // behaves like a struct auto e = d.insertBefore!(1, char[])("another string..."); auto f = e; f.val!(1) = "modified !"; writefln(e.toString); writefln(f.toString); // direct access to fields. the '.val' is an templated alias, not an accessor function f.val!(3) += 2; writefln(typeid(typeof(f.val!(3)))); writefln(f.toString); struct Test { int x; float y; double z; char w; } // no extra costs static assert(Test.sizeof == (Tuple!(int, float, double, char)).sizeof); // easy creation. // "".dup is used because we don't like static arrays. writefln(makeTuple(1, 2.2, 5.f, "foo".dup, 2+7i, "bar".dup).toString); // nest 'em as you like writefln(makeTuple(makeTuple(1, 2), makeTuple(3, 4)).toString);
Jul 07 2006
Kirk McDonald wrote:I've started to write something similar for Pyd, but yours seems more full-featured. One useful function of mine is a tuple_from_fn template, which derives a tuple type directly from a function type, e.g.: void func(int i, char[] s) { } void main() { tuple_from_fn!(typeof(&func)) f; static assert(is(typeof(f) == tuple!(int, char[]))); } The closest thing my tuples have to "bind" is a simple "apply_tuple_to_fn" function that calls the function with the tuple.Ah, I've got it in the Bind module, called 'getFuncArgsTypes'. A simple apply function template is also in the meta package, in its own Apply.d file :)The one question I have is: How well does it handle default function arguments? So far I've managed to support them pretty well in Pyd, and I don't want to break that.I'm afraid that currently it doesn't handle them at all, since it operates on func types, not aliases. Thanks for pointing it out though, I'll have to think about adding support for them :) -- Tomasz Stachowiak /+ a.k.a. h3r3tic +/
Jul 07 2006
Oh joy, this is great! Imho something like this would be nice in Phobos. The FuncMeta module in bind is very useful too. I even managed to make a map function object thanks to this module, such as in the list comprehension thread. It can take a delegate, function or function object (and thus a bound function). I don't think I would have the patience to attempt this in C++... In article <e8m0i6$se2$1 digitaldaemon.com>, Tom S says...Lutger wrote:I'm a little late, but thanks!!! I was hoping somebody would do this. It works like a charm. I tried studying the source, and while it's a LOT better to follow than boost, I discovered I don't understand metaprogramming at all (yet), unfortunatly. Can I ask you, how can I use the Tuple type and what are it's features? This much I figured out: Tuple!(int,int) someTuple; someTuple.val!(1) = 5; assert(someTuple.val!(1) == 5);Thanks for testing and kind words :) I've uploaded an updated version at the same address: http://158.75.59.9/~h3/code/bind.rar As for the Tuple's features, it's really pretty basic, but at the same time quite powerful and allowing for the creation of many interesting templates. I'll use an example to demonstrate its features: Tuple!(int, float) a; a.val!(0) = 5; a.val!(1) = 2.3f; // simple printing writefln(a.toString); // various insertion ops auto b = a.prepend!(char[])("foo"); writefln(b.toString); auto c = b.append!(double)(1.234567); writefln(c.toString); auto d = c.insertAfter!(1, int)(1234); writefln(d.toString); // .length property like in arrays writefln("d.length: ", d.length); // behaves like a struct auto e = d.insertBefore!(1, char[])("another string..."); auto f = e; f.val!(1) = "modified !"; writefln(e.toString); writefln(f.toString); // direct access to fields. the '.val' is an templated alias, not an accessor function f.val!(3) += 2; writefln(typeid(typeof(f.val!(3)))); writefln(f.toString); struct Test { int x; float y; double z; char w; } // no extra costs static assert(Test.sizeof == (Tuple!(int, float, double, char)).sizeof); // easy creation. // "".dup is used because we don't like static arrays. writefln(makeTuple(1, 2.2, 5.f, "foo".dup, 2+7i, "bar".dup).toString); // nest 'em as you like writefln(makeTuple(makeTuple(1, 2), makeTuple(3, 4)).toString); -- Tomasz Stachowiak /+ a.k.a. h3r3tic +/
Jul 07 2006
Tom S wrote:Lutger wrote:Wow! Great peace of code, I really learned a lot from it :) I also agree with Lutger, something like this should be in Phobos/Ares.I'm a little late, but thanks!!! I was hoping somebody would do this. It works like a charm. I tried studying the source, and while it's a LOT better to follow than boost, I discovered I don't understand metaprogramming at all (yet), unfortunatly. Can I ask you, how can I use the Tuple type and what are it's features? This much I figured out: Tuple!(int,int) someTuple; someTuple.val!(1) = 5; assert(someTuple.val!(1) == 5);Thanks for testing and kind words :) I've uploaded an updated version at the same address: http://158.75.59.9/~h3/code/bind.rar
Jul 07 2006