+ All Categories
Home > Documents > How do visitors work? This set of slides traces through the execution of a visitor we’ve seen...

How do visitors work? This set of slides traces through the execution of a visitor we’ve seen...

Date post: 19-Dec-2015
Category:
View: 213 times
Download: 0 times
Share this document with a friend
Popular Tags:
31
How do visitors work? • This set of slides traces through the execution of a visitor we’ve seen before (the lengthVisitor) on a short list. • It shows how the runtime stack makes recursion possible. • First let’s recall: – how the visitor is defined – how ‘execute’ is defined in the two list state classes
Transcript

How do visitors work?

• This set of slides traces through the execution of a visitor we’ve seen before (the lengthVisitor) on a short list.

• It shows how the runtime stack makes recursion possible.

• First let’s recall:– how the visitor is defined– how ‘execute’ is defined in the two list state

classes

Length visitor

• in the empty case the answer is zero• in the non-empty case the answer is one more than

the length of the rest of the list

public Object emptyCase(LRS host, Object _){

return 0;

}

public Object nonEmptyCase(LRS host, Object _){

return 1 + host.getRest().execute(this,_);

}

‘execute’ definition in states

• Empty state:

public Object execute(LRS host, IAlgo visitor, Object input){

return visitor.emptyCase(host, input);

}

• NonEmpty state:

public Object execute(LRS host, IAlgo visitor, Object input){

return visitor.nonEmptyCase(host, input);

}

Now let’s trace execution of the visitor

LRStruct<String> list = new LRStruct<String>();

list.insertFront(“Wilma”).insertFront(“Fred”);

LengthVisitor<String> visitor = new LengthVisitor<String>();

int len = list.execute(visitor,null);

System.out.println(“Length is ” + length);

Focus on the evaluation of:

list.execute(visitor,null)

list

Tracing the execution of a visitor

_state

_datum

_rest

“Fred”

_state

_datum

_rest

“Wilma”

_state

public Object emptyCase(…){…}public Object nonEmptyCase(…){…}

visitor

Driver:int len = list.execute(visitor, null);

LRS:public Object execute(IAlgo algo, Object inp){ return _state.execute(algo, inp, this);}

EmptyState:public <I, O> O execute(IAlgo<I, E, O> algo,

LRStruct<E> host, I arg) { return algo.emptyCase(host, arg);}

NonEmptyState:public <I, O> O execute(IAlgo<I, E, O> algo,

LRStruct<E> host, I arg) { return algo.nonEmptyCase(host, arg);}

LengthVisitor:public Integer emptyCase(LRStruct<E> host, Object _) {

return 0; // isn't autoboxing cool :-)}

public Integer nonEmptyCase(LRStruct<E> host, Object _) {return 1 + host.getRest().execute(this, _);

}

algo

list

Tracing the execution of a visitor

_state

_datum

_rest

“Fred”

_state

_datum

_rest

“Wilma”

_state

public Object emptyCase(…){…}public Object nonEmptyCase(…){…}

space for return valuevisitor

inp (null)

this

Driver:int len = list.execute(visitor, null);

LRS:public Object execute(IAlgo algo, Object inp){ return _state.execute(algo, inp, this);}

EmptyState:public <I, O> O execute(IAlgo<I, E, O> algo,

LRStruct<E> host, I arg) { return algo.emptyCase(host, arg);}

NonEmptyState:public <I, O> O execute(IAlgo<I, E, O> algo,

LRStruct<E> host, I arg) { return algo.nonEmptyCase(host, arg);}

LengthVisitor:public Integer emptyCase(LRStruct<E> host, Object _) {

return 0; // isn't autoboxing cool :-)}

public Integer nonEmptyCase(LRStruct<E> host, Object _) {return 1 + host.getRest().execute(this, _);

}

algo

list

Tracing the execution of a visitor

_state

_datum

_rest

“Fred”

_state

_datum

_rest

“Wilma”

_state

public Object emptyCase(…){…}public Object nonEmptyCase(…){…}

space for return valuevisitor

inp (null)

this

Polymorphi

Polymorphi

cc

method

method

callcall

Driver:int len = list.execute(visitor, null);

LRS:public Object execute(IAlgo algo, Object inp){ return _state.execute(algo, inp, this);}

EmptyState:public <I, O> O execute(IAlgo<I, E, O> algo,

LRStruct<E> host, I arg) { return algo.emptyCase(host, arg);}

NonEmptyState:public <I, O> O execute(IAlgo<I, E, O> algo,

LRStruct<E> host, I arg) { return algo.nonEmptyCase(host, arg);}

LengthVisitor:public Integer emptyCase(LRStruct<E> host, Object _) {

return 0; // isn't autoboxing cool :-)}

public Integer nonEmptyCase(LRStruct<E> host, Object _) {return 1 + host.getRest().execute(this, _);

}

algo

list

Tracing the execution of a visitor

_state

_datum

_rest

“Fred”

_state

_datum

_rest

“Wilma”

_state

public Object emptyCase(…){…}public Object nonEmptyCase(…){…}

visitor

inp (null)

this

this

algo

input (null)

owner

Driver:int len = list.execute(visitor, null);

LRS:public Object execute(IAlgo algo, Object inp){ return _state.execute(algo, inp, this);}

EmptyState:public <I, O> O execute(IAlgo<I, E, O> algo,

LRStruct<E> host, I arg) { return algo.emptyCase(host, arg);}

NonEmptyState:public <I, O> O execute(IAlgo<I, E, O> algo,

LRStruct<E> host, I arg) { return algo.nonEmptyCase(host, arg);}

LengthVisitor:public Integer emptyCase(LRStruct<E> host, Object _) {

return 0; // isn't autoboxing cool :-)}

public Integer nonEmptyCase(LRStruct<E> host, Object _) {return 1 + host.getRest().execute(this, _);

}

this

algo

list

Tracing the execution of a visitor

_state

_datum

_rest

“Fred”

_state

_datum

_rest

“Wilma”

_state

public Object emptyCase(…){…}public Object nonEmptyCase(…){…}

visitor

inp (null)

this

algo

input (null)

owner

this

host

_ (null)

<anonymous>

Driver:int len = list.execute(visitor, null);

LRS:public Object execute(IAlgo algo, Object inp){ return _state.execute(algo, inp, this);}

EmptyState:public <I, O> O execute(IAlgo<I, E, O> algo,

LRStruct<E> host, I arg) { return algo.emptyCase(host, arg);}

NonEmptyState:public <I, O> O execute(IAlgo<I, E, O> algo,

LRStruct<E> host, I arg) { return algo.nonEmptyCase(host, arg);}

LengthVisitor:public Integer emptyCase(LRStruct<E> host, Object _) {

return 0; // isn't autoboxing cool :-)}

public Integer nonEmptyCase(LRStruct<E> host, Object _) {return 1 + host.getRest().execute(this, _);

}

this

algo

list

Tracing the execution of a visitor

_state

_datum

_rest

“Fred”

_state

_datum

_rest

“Wilma”

_state

public Object emptyCase(…){…}public Object nonEmptyCase(…){…}

visitor

inp (null)

this

algo

input (null)

owner

this

host

_ (null)

<anonymous>

algo

inp (null)

this

Driver:int len = list.execute(visitor, null);

LRS:public Object execute(IAlgo algo, Object inp){ return _state.execute(algo, inp, this);}

EmptyState:public <I, O> O execute(IAlgo<I, E, O> algo,

LRStruct<E> host, I arg) { return algo.emptyCase(host, arg);}

NonEmptyState:public <I, O> O execute(IAlgo<I, E, O> algo,

LRStruct<E> host, I arg) { return algo.nonEmptyCase(host, arg);}

LengthVisitor:public Integer emptyCase(LRStruct<E> host, Object _) {

return 0; // isn't autoboxing cool :-)}

public Integer nonEmptyCase(LRStruct<E> host, Object _) {return 1 + host.getRest().execute(this, _);

}

this

algo

list

Tracing the execution of a visitor

_state

_datum

_rest

“Fred”

_state

_datum

_rest

“Wilma”

_state

public Object emptyCase(…){…}public Object nonEmptyCase(…){…}

visitor

inp (null)

this

algo

input (null)

owner

this

host

_ (null)

<anonymous>

algo

inp (null)

this

Polymorphi

Polymorphi

cc

method

method

callcall

Driver:int len = list.execute(visitor, null);

LRS:public Object execute(IAlgo algo, Object inp){ return _state.execute(algo, inp, this);}

EmptyState:public <I, O> O execute(IAlgo<I, E, O> algo,

LRStruct<E> host, I arg) { return algo.emptyCase(host, arg);}

NonEmptyState:public <I, O> O execute(IAlgo<I, E, O> algo,

LRStruct<E> host, I arg) { return algo.nonEmptyCase(host, arg);}

LengthVisitor:public Integer emptyCase(LRStruct<E> host, Object _) {

return 0; // isn't autoboxing cool :-)}

public Integer nonEmptyCase(LRStruct<E> host, Object _) {return 1 + host.getRest().execute(this, _);

}

this

algo

list

Tracing the execution of a visitor

_state

_datum

_rest

“Fred”

_state

_datum

_rest

“Wilma”

_state

public Object emptyCase(…){…}public Object nonEmptyCase(…){…}

visitor

inp (null)

this

algo

input (null)

owner

this

host

_ (null)

<anonymous>

algo

inp (null)

this

this

algo

input (null)

owner

Driver:int len = list.execute(visitor, null);

LRS:public Object execute(IAlgo algo, Object inp){ return _state.execute(algo, inp, this);}

EmptyState:public <I, O> O execute(IAlgo<I, E, O> algo,

LRStruct<E> host, I arg) { return algo.emptyCase(host, arg);}

NonEmptyState:public <I, O> O execute(IAlgo<I, E, O> algo,

LRStruct<E> host, I arg) { return algo.nonEmptyCase(host, arg);}

LengthVisitor:public Integer emptyCase(LRStruct<E> host, Object _) {

return 0; // isn't autoboxing cool :-)}

public Integer nonEmptyCase(LRStruct<E> host, Object _) {return 1 + host.getRest().execute(this, _);

}

this

algo

list

Tracing the execution of a visitor

_state

_datum

_rest

“Fred”

_state

_datum

_rest

“Wilma”

_state

public Object emptyCase(…){…}public Object nonEmptyCase(…){…}

visitor

inp (null)

this

algo

input (null)

owner

this

host

_ (null)

<anonymous>

algo

inp (null)

this

this

algo

input (null)

owner

this

host

_ (null)

<anonymous>

Driver:int len = list.execute(visitor, null);

LRS:public Object execute(IAlgo algo, Object inp){ return _state.execute(algo, inp, this);}

EmptyState:public <I, O> O execute(IAlgo<I, E, O> algo,

LRStruct<E> host, I arg) { return algo.emptyCase(host, arg);}

NonEmptyState:public <I, O> O execute(IAlgo<I, E, O> algo,

LRStruct<E> host, I arg) { return algo.nonEmptyCase(host, arg);}

LengthVisitor:public Integer emptyCase(LRStruct<E> host, Object _) {

return 0; // isn't autoboxing cool :-)}

public Integer nonEmptyCase(LRStruct<E> host, Object _) {return 1 + host.getRest().execute(this, _);

}

this

algo

list

Tracing the execution of a visitor

_state

_datum

_rest

“Fred”

_state

_datum

_rest

“Wilma”

_state

public Object emptyCase(…){…}public Object nonEmptyCase(…){…}

visitor

inp (null)

this

algo

input (null)

owner

this

host

_ (null)

<anonymous>

algo

inp (null)

this

this

algo

input (null)

owner

this

host

_ (null)

<anonymous>

algo

inp (null)

this

Driver:int len = list.execute(visitor, null);

LRS:public Object execute(IAlgo algo, Object inp){ return _state.execute(algo, inp, this);}

EmptyState:public <I, O> O execute(IAlgo<I, E, O> algo,

LRStruct<E> host, I arg) { return algo.emptyCase(host, arg);}

NonEmptyState:public <I, O> O execute(IAlgo<I, E, O> algo,

LRStruct<E> host, I arg) { return algo.nonEmptyCase(host, arg);}

LengthVisitor:public Integer emptyCase(LRStruct<E> host, Object _) {

return 0; // isn't autoboxing cool :-)}

public Integer nonEmptyCase(LRStruct<E> host, Object _) {return 1 + host.getRest().execute(this, _);

}

this

algo

list

Tracing the execution of a visitor

_state

_datum

_rest

“Fred”

_state

_datum

_rest

“Wilma”

_state

public Object emptyCase(…){…}public Object nonEmptyCase(…){…}

visitor

inp (null)

this

algo

input (null)

owner

this

host

_ (null)

<anonymous>

algo

inp (null)

this

this

algo

input (null)

owner

this

host

_ (null)

<anonymous>

algo

inp (null)

this

Polymorphi

Polymorphi

cc

method

method

callcall

Driver:int len = list.execute(visitor, null);

LRS:public Object execute(IAlgo algo, Object inp){ return _state.execute(algo, inp, this);}

EmptyState:public <I, O> O execute(IAlgo<I, E, O> algo,

LRStruct<E> host, I arg) { return algo.emptyCase(host, arg);}

NonEmptyState:public <I, O> O execute(IAlgo<I, E, O> algo,

LRStruct<E> host, I arg) { return algo.nonEmptyCase(host, arg);}

LengthVisitor:public Integer emptyCase(LRStruct<E> host, Object _) {

return 0; // isn't autoboxing cool :-)}

public Integer nonEmptyCase(LRStruct<E> host, Object _) {return 1 + host.getRest().execute(this, _);

}

this

algo

list

Tracing the execution of a visitor

_state

_datum

_rest

“Fred”

_state

_datum

_rest

“Wilma”

_state

public Object emptyCase(…){…}public Object nonEmptyCase(…){…}

visitor

inp (null)

this

algo

input (null)

owner

this

host

_ (null)

<anonymous>

algo

inp (null)

this

this

algo

input (null)

owner

this

host

_ (null)

<anonymous>

algo

inp (null)

this

this

algo

input (null)

owner

Driver:int len = list.execute(visitor, null);

LRS:public Object execute(IAlgo algo, Object inp){ return _state.execute(algo, inp, this);}

EmptyState:public <I, O> O execute(IAlgo<I, E, O> algo,

LRStruct<E> host, I arg) { return algo.emptyCase(host, arg);}

NonEmptyState:public <I, O> O execute(IAlgo<I, E, O> algo,

LRStruct<E> host, I arg) { return algo.nonEmptyCase(host, arg);}

LengthVisitor:public Integer emptyCase(LRStruct<E> host, Object _) {

return 0; // isn't autoboxing cool :-)}

public Integer nonEmptyCase(LRStruct<E> host, Object _) {return 1 + host.getRest().execute(this, _);

}

this

algo

list

Tracing the execution of a visitor

_state

_datum

_rest

“Fred”

_state

_datum

_rest

“Wilma”

_state

public Object emptyCase(…){…}public Object nonEmptyCase(…){…}

visitor

inp (null)

this

algo

input (null)

owner

this

host

_ (null)

<anonymous>

algo

inp (null)

this

this

algo

input (null)

owner

this

host

_ (null)

<anonymous>

algo

inp (null)

this

this

algo

input (null)

owner

0host

_ (null)

this

Driver:int len = list.execute(visitor, null);

LRS:public Object execute(IAlgo algo, Object inp){ return _state.execute(algo, inp, this);}

EmptyState:public <I, O> O execute(IAlgo<I, E, O> algo,

LRStruct<E> host, I arg) { return algo.emptyCase(host, arg);}

NonEmptyState:public <I, O> O execute(IAlgo<I, E, O> algo,

LRStruct<E> host, I arg) { return algo.nonEmptyCase(host, arg);}

LengthVisitor:public Integer emptyCase(LRStruct<E> host, Object _) {

return 0; // isn't autoboxing cool :-)}

public Integer nonEmptyCase(LRStruct<E> host, Object _) {return 1 + host.getRest().execute(this, _);

}

this

algo

list

Tracing the execution of a visitor

_state

_datum

_rest

“Fred”

_state

_datum

_rest

“Wilma”

_state

public Object emptyCase(…){…}public Object nonEmptyCase(…){…}

visitor

inp (null)

this

algo

input (null)

owner

this

host

_ (null)

<anonymous>

algo

inp (null)

this

this

algo

input (null)

owner

this

host

_ (null)

<anonymous>

algo

inp (null)

this

this

algo

input (null)

owner

0

Driver:int len = list.execute(visitor, null);

LRS:public Object execute(IAlgo algo, Object inp){ return _state.execute(algo, inp, this);}

EmptyState:public <I, O> O execute(IAlgo<I, E, O> algo,

LRStruct<E> host, I arg) { return algo.emptyCase(host, arg);}

NonEmptyState:public <I, O> O execute(IAlgo<I, E, O> algo,

LRStruct<E> host, I arg) { return algo.nonEmptyCase(host, arg);}

LengthVisitor:public Integer emptyCase(LRStruct<E> host, Object _) {

return 0; // isn't autoboxing cool :-)}

public Integer nonEmptyCase(LRStruct<E> host, Object _) {return 1 + host.getRest().execute(this, _);

}

this

algo

list

Tracing the execution of a visitor

_state

_datum

_rest

“Fred”

_state

_datum

_rest

“Wilma”

_state

public Object emptyCase(…){…}public Object nonEmptyCase(…){…}

visitor

inp (null)

this

algo

input (null)

owner

this

host

_ (null)

<anonymous>

algo

inp (null)

this

this

algo

input (null)

owner

this

host

_ (null)

<anonymous>

algo

inp (null)

this

0

Driver:int len = list.execute(visitor, null);

LRS:public Object execute(IAlgo algo, Object inp){ return _state.execute(algo, inp, this);}

EmptyState:public <I, O> O execute(IAlgo<I, E, O> algo,

LRStruct<E> host, I arg) { return algo.emptyCase(host, arg);}

NonEmptyState:public <I, O> O execute(IAlgo<I, E, O> algo,

LRStruct<E> host, I arg) { return algo.nonEmptyCase(host, arg);}

LengthVisitor:public Integer emptyCase(LRStruct<E> host, Object _) {

return 0; // isn't autoboxing cool :-)}

public Integer nonEmptyCase(LRStruct<E> host, Object _) {return 1 + host.getRest().execute(this, _);

}

this

algo

list

Tracing the execution of a visitor

_state

_datum

_rest

“Fred”

_state

_datum

_rest

“Wilma”

_state

public Object emptyCase(…){…}public Object nonEmptyCase(…){…}

visitor

inp (null)

this

algo

input (null)

owner

this

host

_ (null)

<anonymous>

algo

inp (null)

this

this

algo

input (null)

owner

this

host

_ (null)

<anonymous>

0

Driver:int len = list.execute(visitor, null);

LRS:public Object execute(IAlgo algo, Object inp){ return _state.execute(algo, inp, this);}

EmptyState:public <I, O> O execute(IAlgo<I, E, O> algo,

LRStruct<E> host, I arg) { return algo.emptyCase(host, arg);}

NonEmptyState:public <I, O> O execute(IAlgo<I, E, O> algo,

LRStruct<E> host, I arg) { return algo.nonEmptyCase(host, arg);}

LengthVisitor:public Integer emptyCase(LRStruct<E> host, Object _) {

return 0; // isn't autoboxing cool :-)}

public Integer nonEmptyCase(LRStruct<E> host, Object _) {return 1 + host.getRest().execute(this, _);

}

this

algo

list

Tracing the execution of a visitor

_state

_datum

_rest

“Fred”

_state

_datum

_rest

“Wilma”

_state

public Object emptyCase(…){…}public Object nonEmptyCase(…){…}

visitor

inp (null)

this

algo

input (null)

owner

this

host

_ (null)

<anonymous>

algo

inp (null)

this

this

algo

input (null)

owner

this

host

_ (null)

<anonymous>

0

1

Driver:int len = list.execute(visitor, null);

LRS:public Object execute(IAlgo algo, Object inp){ return _state.execute(algo, inp, this);}

EmptyState:public <I, O> O execute(IAlgo<I, E, O> algo,

LRStruct<E> host, I arg) { return algo.emptyCase(host, arg);}

NonEmptyState:public <I, O> O execute(IAlgo<I, E, O> algo,

LRStruct<E> host, I arg) { return algo.nonEmptyCase(host, arg);}

LengthVisitor:public Integer emptyCase(LRStruct<E> host, Object _) {

return 0; // isn't autoboxing cool :-)}

public Integer nonEmptyCase(LRStruct<E> host, Object _) {return 1 + host.getRest().execute(this, _);

}

this

algo

list

Tracing the execution of a visitor

_state

_datum

_rest

“Fred”

_state

_datum

_rest

“Wilma”

_state

public Object emptyCase(…){…}public Object nonEmptyCase(…){…}

visitor

inp (null)

this

algo

input (null)

owner

this

host

_ (null)

<anonymous>

algo

inp (null)

this

this

algo

input (null)

owner

0

1

Driver:int len = list.execute(visitor, null);

LRS:public Object execute(IAlgo algo, Object inp){ return _state.execute(algo, inp, this);}

EmptyState:public <I, O> O execute(IAlgo<I, E, O> algo,

LRStruct<E> host, I arg) { return algo.emptyCase(host, arg);}

NonEmptyState:public <I, O> O execute(IAlgo<I, E, O> algo,

LRStruct<E> host, I arg) { return algo.nonEmptyCase(host, arg);}

LengthVisitor:public Integer emptyCase(LRStruct<E> host, Object _) {

return 0; // isn't autoboxing cool :-)}

public Integer nonEmptyCase(LRStruct<E> host, Object _) {return 1 + host.getRest().execute(this, _);

}

this

algo

list

Tracing the execution of a visitor

_state

_datum

_rest

“Fred”

_state

_datum

_rest

“Wilma”

_state

public Object emptyCase(…){…}public Object nonEmptyCase(…){…}

visitor

inp (null)

this

algo

input (null)

owner

this

host

_ (null)

<anonymous>

algo

inp (null)

this

0

1

Driver:int len = list.execute(visitor, null);

LRS:public Object execute(IAlgo algo, Object inp){ return _state.execute(algo, inp, this);}

EmptyState:public <I, O> O execute(IAlgo<I, E, O> algo,

LRStruct<E> host, I arg) { return algo.emptyCase(host, arg);}

NonEmptyState:public <I, O> O execute(IAlgo<I, E, O> algo,

LRStruct<E> host, I arg) { return algo.nonEmptyCase(host, arg);}

LengthVisitor:public Integer emptyCase(LRStruct<E> host, Object _) {

return 0; // isn't autoboxing cool :-)}

public Integer nonEmptyCase(LRStruct<E> host, Object _) {return 1 + host.getRest().execute(this, _);

}

this

algo

list

Tracing the execution of a visitor

_state

_datum

_rest

“Fred”

_state

_datum

_rest

“Wilma”

_state

public Object emptyCase(…){…}public Object nonEmptyCase(…){…}

visitor

inp (null)

this

algo

input (null)

owner

this

host

_ (null)

<anonymous>

0

1

Driver:int len = list.execute(visitor, null);

LRS:public Object execute(IAlgo algo, Object inp){ return _state.execute(algo, inp, this);}

EmptyState:public <I, O> O execute(IAlgo<I, E, O> algo,

LRStruct<E> host, I arg) { return algo.emptyCase(host, arg);}

NonEmptyState:public <I, O> O execute(IAlgo<I, E, O> algo,

LRStruct<E> host, I arg) { return algo.nonEmptyCase(host, arg);}

LengthVisitor:public Integer emptyCase(LRStruct<E> host, Object _) {

return 0; // isn't autoboxing cool :-)}

public Integer nonEmptyCase(LRStruct<E> host, Object _) {return 1 + host.getRest().execute(this, _);

}

this

algo

list

Tracing the execution of a visitor

_state

_datum

_rest

“Fred”

_state

_datum

_rest

“Wilma”

_state

public Object emptyCase(…){…}public Object nonEmptyCase(…){…}

visitor

inp (null)

this

algo

input (null)

owner

this

host

_ (null)

<anonymous>

0

1

2

Driver:int len = list.execute(visitor, null);

LRS:public Object execute(IAlgo algo, Object inp){ return _state.execute(algo, inp, this);}

EmptyState:public <I, O> O execute(IAlgo<I, E, O> algo,

LRStruct<E> host, I arg) { return algo.emptyCase(host, arg);}

NonEmptyState:public <I, O> O execute(IAlgo<I, E, O> algo,

LRStruct<E> host, I arg) { return algo.nonEmptyCase(host, arg);}

LengthVisitor:public Integer emptyCase(LRStruct<E> host, Object _) {

return 0; // isn't autoboxing cool :-)}

public Integer nonEmptyCase(LRStruct<E> host, Object _) {return 1 + host.getRest().execute(this, _);

}

algo

list

Tracing the execution of a visitor

_state

_datum

_rest

“Fred”

_state

_datum

_rest

“Wilma”

_state

public Object emptyCase(…){…}public Object nonEmptyCase(…){…}

visitor

inp (null)

this

this

algo

input (null)

owner

0

1

2

Driver:int len = list.execute(visitor, null);

LRS:public Object execute(IAlgo algo, Object inp){ return _state.execute(algo, inp, this);}

EmptyState:public <I, O> O execute(IAlgo<I, E, O> algo,

LRStruct<E> host, I arg) { return algo.emptyCase(host, arg);}

NonEmptyState:public <I, O> O execute(IAlgo<I, E, O> algo,

LRStruct<E> host, I arg) { return algo.nonEmptyCase(host, arg);}

LengthVisitor:public Integer emptyCase(LRStruct<E> host, Object _) {

return 0; // isn't autoboxing cool :-)}

public Integer nonEmptyCase(LRStruct<E> host, Object _) {return 1 + host.getRest().execute(this, _);

}

algo

list

Tracing the execution of a visitor

_state

_datum

_rest

“Fred”

_state

_datum

_rest

“Wilma”

_state

public Object emptyCase(…){…}public Object nonEmptyCase(…){…}

space for return valuevisitor

inp (null)

this

0

1

2

Driver:int len = list.execute(visitor, null);

LRS:public Object execute(IAlgo algo, Object inp){ return _state.execute(algo, inp, this);}

EmptyState:public <I, O> O execute(IAlgo<I, E, O> algo,

LRStruct<E> host, I arg) { return algo.emptyCase(host, arg);}

NonEmptyState:public <I, O> O execute(IAlgo<I, E, O> algo,

LRStruct<E> host, I arg) { return algo.nonEmptyCase(host, arg);}

LengthVisitor:public Integer emptyCase(LRStruct<E> host, Object _) {

return 0; // isn't autoboxing cool :-)}

public Integer nonEmptyCase(LRStruct<E> host, Object _) {return 1 + host.getRest().execute(this, _);

}

That’s it!

Questions?

Exercise

• Assume you are given an LRS containing Integer objects (all non-null). Write a visitor which traverses the list structure and calculates the sum of all the int values.

• Ex: If the list contains Integers for 1, 2, 3, 4 and 5, the visitor must return an Integer containing 15.

A solutionpublic class SumVisitor implements IAlgo<Object,Integer,Integer> {

// The answer in the case of an empty list is zero// (because zero is the identity element of addition).public Integer emptyCase(LRStruct<Integer> host, Object _) {

return 0; }

// The answer in the case of a non-empty list is the sum of// the first item in the list and the sum of the rest of the // items in the list.public Integer nonEmptyCase(LRStruct<Integer> host, Object _) {

return host.getDatum() + host.getRest().execute(this, _);}

}

Additional exercises

• Write a visitor for an LRS of Integers which returns the largest Integer.

• Write a visitor for an LRS of Integers, which you can assume appear in order from smallest to largest, which inserts its input in the correct (in order) position within the LRS.


Recommended