Dispatching on a variant
language_fan
foo at bar.com.invalid
Sat Sep 26 13:02:16 PDT 2009
Sat, 26 Sep 2009 12:25:23 -0400, Jeremie Pelletier thusly wrote:
> Justin Johansson wrote:
>> language_fan Wrote:
>>
>>> Sat, 26 Sep 2009 09:32:55 -0400, Justin Johansson thusly wrote:
>>>
>>>> I've had a good poke around the forums and couldn't find anything on
>>>> this so ...
>>>>
>>>> What's the recommended method for dispatching code off the runtime
>>>> type of a variant variable (Phobos D2 std.variant)?
>>>>
>>>> Does one use a bunch of
>>>>
>>>> if ( var.peek!(type1)) { ... }
>>>> else if ( var.peek!(type2) { ... }
>>>>
>>>> for all N possible types, or is there a better & faster way with a
>>>> switch or jump table of sorts?
>>> If the type count gets large, how fast it is depends on the backend
>>> optimizations of the compiler. In the worst case it is a O(n) time
>>> linear search. A jump table or almost any other way of dispatching
>>> would be faster. If the variant had an integral tag field, it could be
>>> used in a switch; that way the compiler could easily optimize it
>>> further with the currently available constructs.
>>>
>>> This problem is solved in higher level languages by providing pattern
>>> matching constructs. The compiler is free to optimize the code the way
>>> it likes:
>>>
>>> case var of
>>> type1 => ...
>>> type2 => ...
>>> ...
>>>
>>> But since no C-like language has ever implemented pattern matching, it
>>> might be too radical to add it to D.
>>
>> Thanks both for replies.
>>
>> I've got about 2 dozen types in the variant so the O(n) really hurts.
>> The variant thing seemed like a really cool idea at the time but now
>> ... Without something like suggested above or a computed goto on typeid
>> or Andrei's visitator, it almost pushes me to backout from using
>> variants and having to redesign around some common base class or
>> interface and using virtual function dispatch. :-(
>>
>>
> I see this sort of design in C all the time with event handling,
> although its with unions rather than discriminated unions, the same
> logic applies.
>
> enum EventType {
> Mouse,
> Key,
> Move,
> ...
> }
> struct Event {
> EventType type;
> union {
> MouseEvent mouse;
> KeyEvent key;
> MoveEvent move;
> ...
> }
> }
>
> void dispatchEvent(const(Event)* event) {
> ...
> with(EventType) final switch(event.type) { case Mouse: ...
> case Key: ...
> case Move: ...
> ...
> }
> ...
> }
>
> That's the logic with standard unions, you should be able to get
> something similar with variants. It's more code to setup, but you end up
> with a simple jump table from the switch, and final in D makes it easy
> to change EventType without forgetting to update dispatchEvent.
Exactly, this is what I mentioned previously. Isn't it ugly compared to
type Event = Mouse | Key | Move;
void dispatchEvent(Event event) {
match(event) {
Mouse m => m.squeek();
Key k => ...
...
}
}
What's with all the language proposals here? Why hasn't anyone proposed
this before? This is in fact very helpful - that's why several modern
languages have adopted it.
More information about the Digitalmars-d
mailing list