View mode: basic / threaded / horizontal-split · Log in · Help
August 27, 2012
Visitor pattern revisited in D
/!\ 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
Re: Visitor pattern revisited in D
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
Re: Visitor pattern revisited in D
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
Re: Visitor pattern revisited in D
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
Re: Visitor pattern revisited in D
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
Re: Visitor pattern revisited in D
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
Re: Visitor pattern revisited in D
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
Re: Visitor pattern revisited in D
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
Re: Visitor pattern revisited in D
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
Re: Visitor pattern revisited in D
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; }
}
Top | Discussion index | About this forum | D home