Thread overview
Visitor pattern revisited in D
Aug 27, 2012
deadalnix
Aug 27, 2012
Michal Minich
Aug 27, 2012
Michal Minich
Aug 27, 2012
deadalnix
Aug 27, 2012
Michal Minich
Aug 27, 2012
Pragma Tix
Aug 29, 2012
deadalnix
Aug 28, 2012
Timon Gehr
Aug 29, 2012
deadalnix
Aug 29, 2012
Timon Gehr
August 27, 2012
/!\ 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/
August 27, 2012
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))
August 27, 2012
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.
August 27, 2012
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.
August 27, 2012
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.
August 27, 2012
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


August 28, 2012
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);


August 29, 2012
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.
August 29, 2012
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.
August 29, 2012
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; }
}