Enum double dispatch?

Hello,

This is a design question related to double dispatch, traits, and macros. Please read on if you are interested.

I'm working on a library that deals with collections of items (in my particular case items are arrays of numbers, but this is not important here). While there exist different types of items (and users of the library should be able to define their own), all items share the same basic properties and operations, and these basic properties and operations are all the library needs. Hence it seems a good idea to abstract this with a trait.

Most operations on items deal with a single item only, but there is one very important exception: two items can be combined into a new one (i.e. this is a binary operation).

I can define the Item trait (and provide a few types that implement it) and then write the library relying on that trait. The problem, however, is that it would be really useful to mix different types of items and this crucially involves also being able to combine items of different types with each other (what a combination means depends on the individual types and needs to be defined on a case-by-case basis).

So it seems that for the combination operation I need some kind of double dispatch on item types. Conventional wisdom in such cases seems to be to refer to the visitor pattern, but after having a closer look I do not think that it is appropriate here: visitor works when the set of items is stable, and then allows for custom operations to be defined. But here we have a single operation but want to be able to define new types of items when needed.

So here comes an idea that I had this morning: instead of using the visitor pattern with its chained vtable dispatches or something else (like a hashtable registry storing a pointer to a combine function for each pair of item types), I could simply keep the Item trait and keep the library agnostic about what individual item types are. This will work well for collections of items of one type, but when mixing of different items is needed, one could use a technique related to “enum dispatch” (as provided in the crates enum_dispatch, enum_delegate, or ambassador).

The only difference to classical enum dispatch is that when implementing trait Item for enum AOrB { A(A), B(B) } one will in addition supply the mixed combination operations.

I do not think that the above crates allow defining such mixed operations, but implementing Item for AOrB is definitely possible - if necessary by hand, but this might be an interesting extension to the existing crates.

To me, this “enum double dispatch” technique seems appropriate to my application. It’s zero cost when not needed, but preserves exactly the necessary degrees of freedom: to define own sets of items along with the needed combination operations.

This idea seems rather straightforward, so it would seem that it must have been used already, or else that it has serious downsides that I do not see so far.

Any comments? Thanks!

This topic was automatically closed 90 days after the last reply. We invite you to open a new topic if you have further questions or comments.