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.