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

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

Post on 19-Dec-2015

213 views

Category:

Documents


0 download

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.