www.digitalmars.com         C & C++   DMDScript  

digitalmars.D.announce - Visitor pattern revisited in D

reply deadalnix <deadalnix gmail.com> writes:
/!\ Shameless autopromotion incoming /!\

I have recently put some effort into exploring alternatives to visitor 
pattern and see what can be done in D. I ended up with a solution which 
is a real improvement compared to plein old visitor pattern and wanted 
to share this here.

I think this is short enough to be a good example to show what can be 
done with D capabilities.

http://www.deadalnix.me/2012/08/25/visitor-pattern-revisited-in-d/
Aug 27 2012
next sibling parent "Michal Minich" <michal.minich gmail.com> writes:
On Monday, 27 August 2012 at 15:00:11 UTC, deadalnix wrote:

the "fastCast" could probably be faster this way (I didn't 
checked / compiled)

private U fastCast (U) (object t) {
     return cast(U)(cast(void*)t);
}

one less de/reference.

btw, in your implementation should be (is(T == class) || is(T == 
interface))
Aug 27 2012
prev sibling next sibling parent reply "Michal Minich" <michal.minich gmail.com> writes:
On Monday, 27 August 2012 at 15:00:11 UTC, deadalnix wrote:
 /!\ Shameless autopromotion incoming /!\

 I have recently put some effort into exploring alternatives to 
 visitor pattern and see what can be done in D. I ended up with 
 a solution which is a real improvement compared to plein old 
 visitor pattern and wanted to share this here.

 I think this is short enough to be a good example to show what 
 can be done with D capabilities.

 http://www.deadalnix.me/2012/08/25/visitor-pattern-revisited-in-d/

This is nice use of d magic. If the implementation could recompute the functions pointers during compilation, this seems as nice generally function. This makes me thing of computed goto (to functions) One possibility to achieve this result for visitor is to use mixin. I would mixin implementation of accept method into very node super class. This is to avoid code duplication. Secondly, I would mixin implementation of opDispatch that simply does nothing/throws to every implementation of visitor. This is to avoid empty implementations of visit methods which are not needed for particular visitor.
Aug 27 2012
parent deadalnix <deadalnix gmail.com> writes:
Le 27/08/2012 18:02, Michal Minich a écrit :
 On Monday, 27 August 2012 at 15:00:11 UTC, deadalnix wrote:
 /!\ Shameless autopromotion incoming /!\

 I have recently put some effort into exploring alternatives to visitor
 pattern and see what can be done in D. I ended up with a solution
 which is a real improvement compared to plein old visitor pattern and
 wanted to share this here.

 I think this is short enough to be a good example to show what can be
 done with D capabilities.

 http://www.deadalnix.me/2012/08/25/visitor-pattern-revisited-in-d/

This is nice use of d magic. If the implementation could recompute the functions pointers during compilation, this seems as nice generally function. This makes me thing of computed goto (to functions) One possibility to achieve this result for visitor is to use mixin. I would mixin implementation of accept method into very node super class. This is to avoid code duplication. Secondly, I would mixin implementation of opDispatch that simply does nothing/throws to every implementation of visitor. This is to avoid empty implementations of visit methods which are not needed for particular visitor.

This can only work if you know all node type by advance. Which is one limitation of the visitor pattern I intended to solve.
Aug 27 2012
prev sibling next sibling parent "Michal Minich" <michal.minich gmail.com> writes:
On Monday, 27 August 2012 at 16:28:24 UTC, deadalnix wrote:
 Le 27/08/2012 18:02, Michal Minich a écrit :
 On Monday, 27 August 2012 at 15:00:11 UTC, deadalnix wrote:
 /!\ Shameless autopromotion incoming /!\

 I have recently put some effort into exploring alternatives 
 to visitor
 pattern and see what can be done in D. I ended up with a 
 solution
 which is a real improvement compared to plein old visitor 
 pattern and
 wanted to share this here.

 I think this is short enough to be a good example to show 
 what can be
 done with D capabilities.

 http://www.deadalnix.me/2012/08/25/visitor-pattern-revisited-in-d/

This is nice use of d magic. If the implementation could recompute the functions pointers during compilation, this seems as nice generally function. This makes me thing of computed goto (to functions) One possibility to achieve this result for visitor is to use mixin. I would mixin implementation of accept method into very node super class. This is to avoid code duplication. Secondly, I would mixin implementation of opDispatch that simply does nothing/throws to every implementation of visitor. This is to avoid empty implementations of visit methods which are not needed for particular visitor.

This can only work if you know all node type by advance. Which is one limitation of the visitor pattern I intended to solve.

The opDispatch would only handle non existing methods in visitor. It could be defined to throw, or each visitor could define one doing generic thing for that visitor (ie return null), or visitor could not use opDispatch at all. Generally I think default imlementations of interface methods - such as to throw/do nothing/return null should not be used. Then I think is better to split the interface/hierarchy of clases. This may not be allways better solution. Large hierarchy of clases can be hiding some middle clases, wich could lead to beterr desing, if lucky. But here it depend on specifics if its better to introduce hierarchy, or handle some specifics here and there.
Aug 27 2012
prev sibling next sibling parent reply Pragma Tix <pragmatix orange.fr> writes:
Am 27.08.2012 17:00, schrieb deadalnix:
 I have recently put some effort into exploring alternatives to visitor
 pattern and see what can be done in D. I ended up with a solution which
 is a real improvement compared to plein old visitor pattern and wanted
 to share this here.

Thanks 4 sharing, Once I had a hope for std.pattern (Eiffel library like) but.. this was long time ago D 1 or so.. Maybe your code is an improvement over conventional OO code (i doubt it) , but for sure plain old readability/ and understanding of code gets completely lost. Despite that, IF you want to use the visitor pattern to do AST walking, make sure that u understand the Hierarchical Visitor Pattern. Anyway.. I (just me) find your code hard to understand,UN-maintainable in other words : Yet Another Reason To Consider D2 Unusable. A language should not allow such things. auto dispatch( alias unhandled = function typeof(null)(t) { throw new Exception(typeid(t).toString() ~ " is not supported by visitor " ~ typeid(V).toString() ~ " ."); }, V, T )(ref V visitor, T t) if(is(T == class) || is(T == interface)) .................... If you consider this as smart code you should see your doctor really soon.. my 2 cents
Aug 27 2012
parent deadalnix <deadalnix gmail.com> writes:
Le 28/08/2012 00:20, Pragma Tix a crit :
 Am 27.08.2012 17:00, schrieb deadalnix:
 auto dispatch(
 alias unhandled = function typeof(null)(t) {
 throw new Exception(typeid(t).toString() ~ " is not supported by visitor
 " ~ typeid(V).toString() ~ " .");
 }, V, T
 )(ref V visitor, T t) if(is(T == class) || is(T == interface))
 ....................

 If you consider this as smart code you should see your doctor really
 soon.. my 2 cents

The whole point is that you don't need to do this crazy stuff. You can just use it. It make the code a lot cleaner in all other places and improve what you can do with a plein old visitor pattern.
Aug 28 2012
prev sibling parent reply Timon Gehr <timon.gehr gmx.ch> writes:
On 08/27/2012 05:00 PM, deadalnix wrote:
 /!\ Shameless autopromotion incoming /!\

 I have recently put some effort into exploring alternatives to visitor
 pattern and see what can be done in D. I ended up with a solution which
 is a real improvement compared to plein old visitor pattern and wanted
 to share this here.

 I think this is short enough to be a good example to show what can be
 done with D capabilities.

 http://www.deadalnix.me/2012/08/25/visitor-pattern-revisited-in-d/

An issue is that the proposed scheme does not support subclassing a node to tweak its behaviour without changing the way the visitor operates on it. i.e. it violates the substitution principle by default. You can return void expressions from void functions, this is a deliberate design decision to make generic code less noisy. static if(is(typeof(return) == void)) { unhandled(o); } else { return unhandled(o); } ==> return unhandled(o);
Aug 28 2012
parent reply deadalnix <deadalnix gmail.com> writes:
Le 28/08/2012 17:39, Timon Gehr a crit :
 On 08/27/2012 05:00 PM, deadalnix wrote:
 /!\ Shameless autopromotion incoming /!\

 I have recently put some effort into exploring alternatives to visitor
 pattern and see what can be done in D. I ended up with a solution which
 is a real improvement compared to plein old visitor pattern and wanted
 to share this here.

 I think this is short enough to be a good example to show what can be
 done with D capabilities.

 http://www.deadalnix.me/2012/08/25/visitor-pattern-revisited-in-d/

An issue is that the proposed scheme does not support subclassing a node to tweak its behaviour without changing the way the visitor operates on it. i.e. it violates the substitution principle by default.

It does indeed. This is why I started by stating that we are interested in object as data abstraction here, not as behavioral one.
 You can return void expressions from void functions, this is a
 deliberate design decision to make generic code less noisy.

 static if(is(typeof(return) == void)) {
 unhandled(o);
 } else {
 return unhandled(o);
 }

 ==>

 return unhandled(o);

unhandled isn't void. And typeof(return) isn't available at unhandled definition point. That was my first short, but I couldn't make it work.
Aug 28 2012
parent Timon Gehr <timon.gehr gmx.ch> writes:
On 08/29/2012 02:24 AM, deadalnix wrote:
 Le 28/08/2012 17:39, Timon Gehr a crit :
 On 08/27/2012 05:00 PM, deadalnix wrote:
 /!\ Shameless autopromotion incoming /!\

 I have recently put some effort into exploring alternatives to visitor
 pattern and see what can be done in D. I ended up with a solution which
 is a real improvement compared to plein old visitor pattern and wanted
 to share this here.

 I think this is short enough to be a good example to show what can be
 done with D capabilities.

 http://www.deadalnix.me/2012/08/25/visitor-pattern-revisited-in-d/

An issue is that the proposed scheme does not support subclassing a node to tweak its behaviour without changing the way the visitor operates on it. i.e. it violates the substitution principle by default.

It does indeed. This is why I started by stating that we are interested in object as data abstraction here, not as behavioral one. ...

There is no obvious difference between data and behaviour. class A: Node{ auto visit(...){...} int getFoo(){ return foo; } } class B: A{ override int getFoo(){ return 2*foo; } }
Aug 28 2012