Date post: | 19-Dec-2015 |
Category: |
Documents |
View: | 213 times |
Download: | 0 times |
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, _);
}
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, _);}
}