yet another multimethods library

classic Classic list List threaded Threaded
12 messages Options
Reply | Threaded
Open this post in threaded view
|

yet another multimethods library

Korcan Hussein
Hi, i'm on the verge of completing a first release of a fully featured
multimethods component for C++, one in which i believe goes beyond anything
currently available and is very suited to become part of boost. I'm fully
aware of Jesse Jones's contribution however his library has not become an
offical part of boost and i believe my version takes things much further in
thew different ways and i have some nice ideas for the next version to make
even better.

It's inspired by boost/std::tr1::function and CLOS generic functions and
thus works like bost::/std::tr1::function preferred syntax ALA function
types e.g:

typedef boost::shared_ptr<fuzz> fuzz_ptr;

generic_function< void (const foo&, int, bar*, float,  fuzz_ptr) > foobar;

where foo, bar and fuzz are polymorphic types and automatically are
considered for multiple dispatch, detection of which arguments are choosen
for dispatch is automated (and yes there already is support for smart/proxy
pointers/references in place with std::auto_ptr,
boost::/std::tr1::shared/intrusive_ptr working out-the-box). The order and
placement of arguments is irrelevant and non-polymorphic arguments are
totally allowed, covariant return types comes for free and work similar to
covariant return types of virtual member functions.

I think i'll just stop writing about the library any further (abit more to
it than this) i just like to know if you guys are interested in making this
an offical part of boost and to be worked on further by myself and with the
help of others.

P.S By the way this has been built with boost mpl, preprocessor and type
traits from the beginning and interlope with other boost components in mind
i.e phoenix, lambda, fusion, bind, function etc, etc.



_______________________________________________
Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost
Reply | Threaded
Open this post in threaded view
|

Re: yet another multimethods library

Fred Bertsch
I recently had to implement something similar for a project I'm
working on. I would certainly like to see something more complete than
what I came up with placed in boost.

-Fred

On 3/1/06, Korcan Hussein <[hidden email]> wrote:

> Hi, i'm on the verge of completing a first release of a fully featured
> multimethods component for C++, one in which i believe goes beyond anything
> currently available and is very suited to become part of boost. I'm fully
> aware of Jesse Jones's contribution however his library has not become an
> offical part of boost and i believe my version takes things much further in
> thew different ways and i have some nice ideas for the next version to make
> even better.
>
> It's inspired by boost/std::tr1::function and CLOS generic functions and
> thus works like bost::/std::tr1::function preferred syntax ALA function
> types e.g:
>
> typedef boost::shared_ptr<fuzz> fuzz_ptr;
>
> generic_function< void (const foo&, int, bar*, float,  fuzz_ptr) > foobar;
>
> where foo, bar and fuzz are polymorphic types and automatically are
> considered for multiple dispatch, detection of which arguments are choosen
> for dispatch is automated (and yes there already is support for smart/proxy
> pointers/references in place with std::auto_ptr,
> boost::/std::tr1::shared/intrusive_ptr working out-the-box). The order and
> placement of arguments is irrelevant and non-polymorphic arguments are
> totally allowed, covariant return types comes for free and work similar to
> covariant return types of virtual member functions.
>
> I think i'll just stop writing about the library any further (abit more to
> it than this) i just like to know if you guys are interested in making this
> an offical part of boost and to be worked on further by myself and with the
> help of others.
>
> P.S By the way this has been built with boost mpl, preprocessor and type
> traits from the beginning and interlope with other boost components in mind
> i.e phoenix, lambda, fusion, bind, function etc, etc.
>
>
>
> _______________________________________________
> Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost
>


--
F

_______________________________________________
Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost
Reply | Threaded
Open this post in threaded view
|

Re: yet another multimethods library

David Abrahams
In reply to this post by Korcan Hussein
"Korcan Hussein" <[hidden email]> writes:

> I think i'll just stop writing about the library any further (abit more to
> it than this) i just like to know if you guys are interested in making this
> an offical part of boost and to be worked on further by myself and with the
> help of others.

Sounds fascinating; show me more!

--
Dave Abrahams
Boost Consulting
www.boost-consulting.com

_______________________________________________
Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost
Reply | Threaded
Open this post in threaded view
|

Re: yet another multimethods library

Joel de Guzman-2
David Abrahams wrote:

> "Korcan Hussein" <[hidden email]> writes:
>
>
>>I think i'll just stop writing about the library any further (abit more to
>>it than this) i just like to know if you guys are interested in making this
>>an offical part of boost and to be worked on further by myself and with the
>>help of others.
>
>
> Sounds fascinating; show me more!

Wow! Gimme gimme gimme! :)

Cheers,
--
Joel de Guzman
http://www.boost-consulting.com
http://spirit.sf.net

_______________________________________________
Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost
Reply | Threaded
Open this post in threaded view
|

Re: yet another multimethods library

Korcan Hussein
In reply to this post by David Abrahams
"David Abrahams" <[hidden email]> wrote in message
news:<[hidden email]>...

>

> Sounds fascinating; show me more!

>

Heh, okay I still have a little way left to go but the "shell" of it is
pretty much complete as well as most of the guts of it. Okay I'll try to
elaborate a bit more about this.

Lets start with what the client gets to play with, well you have a choice of
two similar but different kinds of front-ends. The first and main one is
(currently) called generic function (maybe it should change it to something
like boost::generic::function instead?). This component allows any kind of
C++ callable entity to be registered for dynamic dispatch, as you could
probably guess it gets a little help from boost::function in this department
:). quick example:

// single dispatch

generic_function< void (boost::shared_ptr<foo>, float) > print_foo;

const bool reg[] = {

print_foo.def_method< boost::shared_ptr<bar> >(print_bar),

print_foo.def_method< boost::shared_ptr<fuzz> >(print_fuzz)

};

.....

boost::shared_ptr<foo> foo_ptr(new fuzz);

print_foo(foo_ptr, 0.0f);

/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

// multiple dispatch ( farfetched example :) )

typedef float (my_sig)(const std::string&, const base1&, float, Base2*,
std::string,
                                 boost::intrusive_ptr<base3>, base1**,
Base2*&, wrap<const base3&>);

// const base1&, Base2*, boost::intrusive_ptr<base3> are selected for
dispatch,
// base1**, Base2*&, wrap<const base3&> are not selected for very good
reasons!
// "wrap" is a trivial metafunction clients can use to disable the automated
deduction.

generic_function< my_sig > foobar;

const bool reg[] = {

foobar.def_method< const dev1_1&, dev2_1*, boost::intrusive_ptr<dev3_1>
 >(func_obj1),

foobar.def_method< const dev1_2&, dev2_2*, boost::intrusive_ptr<dev3_2>
 >(func_obj2),

foobar.def_method< const dev1_3&, dev2_3*, boost::intrusive_ptr<dev3_3>
 >(func_obj3)

};

Of-course you are not required to register functions all at once and this is
completely non-intrusive solution, I'm just doing it here for illustrative
purposes. As you can see the registration process is a little nasty (open to
suggestions & debate), unfortunately because of pointer/reference *proxy*
support CV qualification and raw pointer/reference is required, fortunately
forgetful clients will be caught at compile-time :). Only sub-types are
required to be stated and the reason they are required is it's not possible
to deduce argument types of function objects however I could write an
overload that can deduce types for free-functions ala
boost::function_traits.

As of current this is the only place where the order sub-types should come
in the same order stated to generic_function but generic_function itself
does not care for order and placement of arguments of polymorphic types,
again mistakes will be caught out before they have a chance :).

Now I'll briefly describe the other front-end called fast_generic_function
for a lack of a better name the only difference it has from generic_function
is it should have less overhead in terms of storage & runtime (but maybe
slightly longer compile-time) because it deals solely with pointer to
functions as opposed to boost::function, also "def_method" member function
for fast_generic_function is used slightly different an example using the
first example above would be:

const bool reg[] = {

print_foo.def_method< void (boost::shared_ptr<bar>, float), print_bar >(),

print_foo.def_method< void (boost::shared_ptr<fuzz>, float), print_fuzz >()

};

Both generic_function and fast_generic_function use the same backend called
generic_functionN (this might change latter in into two classes
generic_base_fun and generic_functionN but this is of no concern to
clients), they are all parameterized by allocator type and default to use
std::allocator of-course.

As of current exact method matches are an (amortized) constant time
operation, as you can pretty much guess a hash map is used that maps a tuple
of type identifies to either function pointers or boost::function (depending
on which front-end is used). I'm currently using boost::fusion::vector
instead of boost::tuples/std::tr1::tuple because it's a bit more flexible to
work with but I'm going to change it to use boost::tuples::tuple simply for
the reason that boost::fusion isn't (yet) currently an official part of
boost. Boost.Functional/Hash is also used.

I'm going to investigate boost::multi_index_container as an alternative so
there could be a possibility of (amortized) constant time exact matches and
logarithmic time best matches. That is what I'm going to explore this
weekend and adding method combinations (before, after around,
call-next-method etc).

Let me emphasize one thing I'm trying my utmost to keep compile-times and
code bloat to the minimum as much as possible, taking advantage of lazy
evaluation (lazy template instantiation) via MPL views where ever possible
etc, etc.

(Possible) Future directions I would like to see:

support for boost::any, be the end for type-switching code on many anys ^_^,

Move semantics,

Further improve efficiency,

Reduce compile-times further,

Use "Multiple Row Displacement" algorithm,

And the ultimate aim is to have support for Predicate dispatching in C++ if
it's possible at all (highly doubt it). For those who don't know Predicate
dispatching is a further generalization of multimethods with some ML pattern
matching goodness.

P.S. I forgot to mention this *as of current* RTTI support needs to be
enabled, it's not as bad as it may sound, it is only required in one place
and that is determining type identities via typeid operator at runtime this
is the only decent way to make this solution non-intrusive and loosely
coupled. Besides i've read that invoking the typeid operator is an amortized
constant time operation however I cannot find any confirmation of this in
the current C++ standard does anybody for sure?.



_______________________________________________
Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost
Reply | Threaded
Open this post in threaded view
|

Re: yet another multimethods library

Korcan Hussein
In reply to this post by Korcan Hussein
So what do you guys think thus far? anything you like/dislike and/or
suggestions?.



_______________________________________________
Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost
Reply | Threaded
Open this post in threaded view
|

Re: yet another multimethods library

Pavel Vozenilek

"Korcan Hussein" wrote:
>
> So what do you guys think thus far? anything you like/dislike and/or
> suggestions?.
 Please put the library into Boost Vault:
http://boost-consulting.com/vault/

I guess many are curious on it.

/Pavel



_______________________________________________
Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost
Reply | Threaded
Open this post in threaded view
|

Re: yet another multimethods library (need a hand here)

Korcan Hussein
In reply to this post by Korcan Hussein
Hiya, I've pretty much finished thus far with the shell (all the boost.mpl &
boost.preprocessor side of it).

I initially had a stub implementation using a hash map that maps a tuple of
type identifiers to either a pointer to function or boost::function where a
hashing was based off the string of the type identifier.

This allowed for exact matches only so over the weekend I played around with
idea of using boost::multi_index_container to allow me gain (amortized)
constant time exact matches using hashed indices and logarithmic time
inexact/nearest/best matches using ordered indices.

After a thew attempts i've become pretty much stumped on getting
best/nearest matches to work for all combinations correctly, there is always
one odd case where the set of applicable methods leaves out a more
correct/better method that is available. Also i'm not sure if this method
would handle multiple/virtual inheritance correctly (i've not tried it yet).

Another thing i relized was that hased indicies has issues of symmetric
methods/functions (while ordered indicies of-course doesn't).

So i was wondering if anyone can point me in the right direction or a give
me hand on dealing with the best/nearest matches in conjunction with
boost::multi_index_container or suggest another alternative. Once this bit
is done i'll upload it to boost vault :).

Thanks Korcan.



_______________________________________________
Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost
Reply | Threaded
Open this post in threaded view
|

Re: yet another multimethods library (need a hand here)

Joaquin M LópezMuñoz

Korcan Hussein ha escrito:
[...]

> Another thing i relized was that hased indicies has issues of symmetric
> methods/functions (while ordered indicies of-course doesn't).

I don't know what you mean here.

>
>
> So i was wondering if anyone can point me in the right direction or a give
> me hand on dealing with the best/nearest matches in conjunction with
> boost::multi_index_container or suggest another alternative.

Hello Korcan,

I'm quite proficient in Boost.MultiIndex so maybe I can be of some help.
Unfortunately, I'm not understading the explanation of your current probem,
probably for lack of context. If you could provide me (either privately
or through the list) with some more info and some code to have a look at,
I can  try to help.

Best,

Joaquín M López Muñoz
Telefónica, Investigación y Desarrollo

_______________________________________________
Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost
Reply | Threaded
Open this post in threaded view
|

Re: yet another multimethods library (need a hand here)

Korcan Hussein
> "Joaquín Mª López Muñoz" <[hidden email]> wrote in message
> news:[hidden email]...
>
> I don't know what you mean here.

I was just talking about symmetry of multimethods, say you had a generic
function declaration such as:

generic_function< void (const bar&, const bar&) > gen_fun;

and you register a function like so:

gen_fun.def_method< const foo&, const baz& >(fun);  // where foo & baz are
sub-types of bar

Now say you have 2 variables to use with this generic function that have
there arguments the other way round:

baz b;
foo b;

gen_fun(b, f);

Now the hashed indices view will not find a matching function because the
original function registered was with a combined hashed of the type
identifiers of foo then baz but the combined hash of the type identifiers of
baz then foo is not the same hash value which makes sense. It's not a
problem with boost::multi_index_container it's just a slight flaw in my
logic :)

It's not to much of a problem since an ordered view would still pick this up
but it's not an (amortized) constant time operation it's logarithmic time.

>
> I'm quite proficient in Boost.MultiIndex so maybe I can be of some help.
> Unfortunately, I'm not understading the explanation of your current
> probem,
> probably for lack of context. If you could provide me (either privately
> or through the list) with some more info and some code to have a look at,
> I can  try to help.
>

Thanks, i think i've managed to sort it now, it's wasn't an issue of using
boost::multi_index_container per-say.

Now i've stumbed on another issue, originally the predicate function i was
using for the keys of the ordered indices view was simply
std::type_info::before but this causes some slight problems because
std::type_info::before only gives a collating order of types, it does not
tell you if one std::type_info instance is a sub/super-type of another only
if one type proceeds another.

I can't use type traits any more since this is dealing with the runtime
world. I can't use dynamic_cast to make runtime type queries because I have
std::type_info instances not static types.

So does anybody know of a good method to determine if one std::type_info is
a sub/super-type or another std::type_info.




_______________________________________________
Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost
Reply | Threaded
Open this post in threaded view
|

Re: yet another multimethods library (need a hand here)

David Abrahams
"Korcan Hussein" <[hidden email]> writes:

> So does anybody know of a good method to determine if one std::type_info is
> a sub/super-type or another std::type_info.

There's no portable way to do it without explicitly registering
base/derived relationships.

--
Dave Abrahams
Boost Consulting
www.boost-consulting.com

_______________________________________________
Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost
Reply | Threaded
Open this post in threaded view
|

Re: yet another multimethods library (need a hand here)

Korcan Hussein
"David Abrahams" <[hidden email]> wrote in message
news:[hidden email]...
> "Korcan Hussein" <[hidden email]> writes:
>
>> So does anybody know of a good method to determine if one std::type_info
>> is
>> a sub/super-type or another std::type_info.
>
> There's no portable way to do it without explicitly registering
> base/derived relationships.
>

I thought as much, worth a try though  ;-)

while i'm pondering ideas i'm open to any suggestions people may have :)



_______________________________________________
Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost