Thread overview
A library similar to boost::bind
Jun 18, 2006
Tom S
Jul 07, 2006
Lutger
Jul 07, 2006
Tom S
Jul 07, 2006
Kirk McDonald
Jul 07, 2006
Tom S
Jul 08, 2006
Lutger
Jul 08, 2006
Ivan Senji
June 18, 2006
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 +/
July 07, 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 +/


July 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 +/
July 07, 2006
Tom S wrote:
> 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);
> 
> 
> 

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/wiki
July 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 +/
July 08, 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 +/


July 08, 2006
Tom S wrote:
> 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
> 

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.