Talk tonight Richard Stallman Norton 112 6:00 PM
SumVisitor 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.
SumVisitor exercise Done interactively, from scratch, in Eclipse. Final version in lrstruct.visitors package in SP10-CSE116-LRStruct project.
SumVisitor solution public class SumVisitor implements IAlgo { // The answer in the case of an empty list is zero // (because zero is the identity element of addition). public Integer emptyCase(LRStruct 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 host, Object _) { return host.getDatum() + host.getRest().execute(this, _); }
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 Integer emptyCase(LRStruct host, Object _){ return 0; } public Integer nonEmptyCase(LRStruct host, Object _){ return 1 + host.getRest().execute(this,_); }
‘execute’ definition in states Empty state: public Object execute(LRS host, IAlgo algo, Object argut){ return algo.emptyCase(host, input); } NonEmpty state: public Object execute(LRS host, IAlgo algo, Object argut){ return algo.nonEmptyCase(host, input); }
Now let’s trace execution of the visitor LRStruct list = new LRStruct (); list.insertFront(“Wilma”).insertFront(“Fred”); LengthVisitor visitor = new LengthVisitor (); 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 arg){ return _state.execute(algo, arg, this); } EmptyState: public O execute(IAlgo algo, LRStruct host, I arg) { return algo.emptyCase(host, arg); } NonEmptyState: public O execute(IAlgo algo, LRStruct host, I arg) { return algo.nonEmptyCase(host, arg); } LengthVisitor: public Integer emptyCase(LRStruct host, Object _) { return 0; // isn't autoboxing cool :-) } public Integer nonEmptyCase(LRStruct 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 value visitor arg (null) this Driver: int len = list.execute(visitor, null); LRS: public Object execute(IAlgo algo, Object arg){ return _state.execute(algo, arg, this); } EmptyState: public O execute(IAlgo algo, LRStruct host, I arg) { return algo.emptyCase(host, arg); } NonEmptyState: public O execute(IAlgo algo, LRStruct host, I arg) { return algo.nonEmptyCase(host, arg); } LengthVisitor: public Integer emptyCase(LRStruct host, Object _) { return 0; // isn't autoboxing cool :-) } public Integer nonEmptyCase(LRStruct 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 value visitor arg (null) this Polymorphic method call Driver: int len = list.execute(visitor, null); LRS: public Object execute(IAlgo algo, Object arg){ return _state.execute(algo, arg, this); } EmptyState: public O execute(IAlgo algo, LRStruct host, I arg) { return algo.emptyCase(host, arg); } NonEmptyState: public O execute(IAlgo algo, LRStruct host, I arg) { return algo.nonEmptyCase(host, arg); } LengthVisitor: public Integer emptyCase(LRStruct host, Object _) { return 0; // isn't autoboxing cool :-) } public Integer nonEmptyCase(LRStruct 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 arg (null) this algo arg (null) host Driver: int len = list.execute(visitor, null); LRS: public Object execute(IAlgo algo, Object arg){ return _state.execute(algo, arg, this); } EmptyState: public O execute(IAlgo algo, LRStruct host, I arg) { return algo.emptyCase(host, arg); } NonEmptyState: public O execute(IAlgo algo, LRStruct host, I arg) { return algo.nonEmptyCase(host, arg); } LengthVisitor: public Integer emptyCase(LRStruct host, Object _) { return 0; // isn't autoboxing cool :-) } public Integer nonEmptyCase(LRStruct 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 arg (null) this algo arg (null) host this host _ (null) Driver: int len = list.execute(visitor, null); LRS: public Object execute(IAlgo algo, Object arg){ return _state.execute(algo, arg, this); } EmptyState: public O execute(IAlgo algo, LRStruct host, I arg) { return algo.emptyCase(host, arg); } NonEmptyState: public O execute(IAlgo algo, LRStruct host, I arg) { return algo.nonEmptyCase(host, arg); } LengthVisitor: public Integer emptyCase(LRStruct host, Object _) { return 0; // isn't autoboxing cool :-) } public Integer nonEmptyCase(LRStruct 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 arg (null) this algo arg (null) host this host _ (null) algo arg (null) this Driver: int len = list.execute(visitor, null); LRS: public Object execute(IAlgo algo, Object arg){ return _state.execute(algo, arg, this); } EmptyState: public O execute(IAlgo algo, LRStruct host, I arg) { return algo.emptyCase(host, arg); } NonEmptyState: public O execute(IAlgo algo, LRStruct host, I arg) { return algo.nonEmptyCase(host, arg); } LengthVisitor: public Integer emptyCase(LRStruct host, Object _) { return 0; // isn't autoboxing cool :-) } public Integer nonEmptyCase(LRStruct 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 arg (null) this algo arg (null) host this host _ (null) algo arg (null) this Polymorphic method call Driver: int len = list.execute(visitor, null); LRS: public Object execute(IAlgo algo, Object arg){ return _state.execute(algo, arg, this); } EmptyState: public O execute(IAlgo algo, LRStruct host, I arg) { return algo.emptyCase(host, arg); } NonEmptyState: public O execute(IAlgo algo, LRStruct host, I arg) { return algo.nonEmptyCase(host, arg); } LengthVisitor: public Integer emptyCase(LRStruct host, Object _) { return 0; // isn't autoboxing cool :-) } public Integer nonEmptyCase(LRStruct 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 arg (null) this algo arg (null) host this host _ (null) algo arg (null) this algo arg (null) host Driver: int len = list.execute(visitor, null); LRS: public Object execute(IAlgo algo, Object arg){ return _state.execute(algo, arg, this); } EmptyState: public O execute(IAlgo algo, LRStruct host, I arg) { return algo.emptyCase(host, arg); } NonEmptyState: public O execute(IAlgo algo, LRStruct host, I arg) { return algo.nonEmptyCase(host, arg); } LengthVisitor: public Integer emptyCase(LRStruct host, Object _) { return 0; // isn't autoboxing cool :-) } public Integer nonEmptyCase(LRStruct 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 arg (null) this algo arg (null) host this host _ (null) algo arg (null) this algo arg (null) host this host _ (null) Driver: int len = list.execute(visitor, null); LRS: public Object execute(IAlgo algo, Object arg){ return _state.execute(algo, arg, this); } EmptyState: public O execute(IAlgo algo, LRStruct host, I arg) { return algo.emptyCase(host, arg); } NonEmptyState: public O execute(IAlgo algo, LRStruct host, I arg) { return algo.nonEmptyCase(host, arg); } LengthVisitor: public Integer emptyCase(LRStruct host, Object _) { return 0; // isn't autoboxing cool :-) } public Integer nonEmptyCase(LRStruct 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 arg (null) this algo arg (null) host this host _ (null) algo arg (null) this algo arg (null) host this host _ (null) algo arg (null) this Driver: int len = list.execute(visitor, null); LRS: public Object execute(IAlgo algo, Object arg){ return _state.execute(algo, arg, this); } EmptyState: public O execute(IAlgo algo, LRStruct host, I arg) { return algo.emptyCase(host, arg); } NonEmptyState: public O execute(IAlgo algo, LRStruct host, I arg) { return algo.nonEmptyCase(host, arg); } LengthVisitor: public Integer emptyCase(LRStruct host, Object _) { return 0; // isn't autoboxing cool :-) } public Integer nonEmptyCase(LRStruct 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 arg (null) this algo arg (null) host this host _ (null) algo arg (null) this algo arg (null) host this host _ (null) algo arg (null) this Polymorphic method call Driver: int len = list.execute(visitor, null); LRS: public Object execute(IAlgo algo, Object arg){ return _state.execute(algo, arg, this); } EmptyState: public O execute(IAlgo algo, LRStruct host, I arg) { return algo.emptyCase(host, arg); } NonEmptyState: public O execute(IAlgo algo, LRStruct host, I arg) { return algo.nonEmptyCase(host, arg); } LengthVisitor: public Integer emptyCase(LRStruct host, Object _) { return 0; // isn't autoboxing cool :-) } public Integer nonEmptyCase(LRStruct 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 arg (null) this algo arg (null) host this host _ (null) algo arg (null) this algo arg (null) host this host _ (null) algo arg (null) this algo arg (null) host Driver: int len = list.execute(visitor, null); LRS: public Object execute(IAlgo algo, Object arg){ return _state.execute(algo, arg, this); } EmptyState: public O execute(IAlgo algo, LRStruct host, I arg) { return algo.emptyCase(host, arg); } NonEmptyState: public O execute(IAlgo algo, LRStruct host, I arg) { return algo.nonEmptyCase(host, arg); } LengthVisitor: public Integer emptyCase(LRStruct host, Object _) { return 0; // isn't autoboxing cool :-) } public Integer nonEmptyCase(LRStruct 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 arg (null) this algo arg (null) host this host _ (null) algo arg (null) this algo arg (null) host this host _ (null) algo arg (null) this algo arg (null) host 0 _ (null) this Driver: int len = list.execute(visitor, null); LRS: public Object execute(IAlgo algo, Object arg){ return _state.execute(algo, arg, this); } EmptyState: public O execute(IAlgo algo, LRStruct host, I arg) { return algo.emptyCase(host, arg); } NonEmptyState: public O execute(IAlgo algo, LRStruct host, I arg) { return algo.nonEmptyCase(host, arg); } LengthVisitor: public Integer emptyCase(LRStruct host, Object _) { return 0; // isn't autoboxing cool :-) } public Integer nonEmptyCase(LRStruct 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 arg (null) this algo arg (null) host this host _ (null) algo arg (null) this algo arg (null) host this host _ (null) algo arg (null) this algo arg (null) host 0 Driver: int len = list.execute(visitor, null); LRS: public Object execute(IAlgo algo, Object arg){ return _state.execute(algo, arg, this); } EmptyState: public O execute(IAlgo algo, LRStruct host, I arg) { return algo.emptyCase(host, arg); } NonEmptyState: public O execute(IAlgo algo, LRStruct host, I arg) { return algo.nonEmptyCase(host, arg); } LengthVisitor: public Integer emptyCase(LRStruct host, Object _) { return 0; // isn't autoboxing cool :-) } public Integer nonEmptyCase(LRStruct 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 arg (null) this algo arg (null) host this host _ (null) algo arg (null) this algo arg (null) host this host _ (null) algo arg (null) this 0 Driver: int len = list.execute(visitor, null); LRS: public Object execute(IAlgo algo, Object arg){ return _state.execute(algo, arg, this); } EmptyState: public O execute(IAlgo algo, LRStruct host, I arg) { return algo.emptyCase(host, arg); } NonEmptyState: public O execute(IAlgo algo, LRStruct host, I arg) { return algo.nonEmptyCase(host, arg); } LengthVisitor: public Integer emptyCase(LRStruct host, Object _) { return 0; // isn't autoboxing cool :-) } public Integer nonEmptyCase(LRStruct 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 arg (null) this algo arg (null) host this host _ (null) algo arg (null) this algo arg (null) host this host _ (null) 0 Driver: int len = list.execute(visitor, null); LRS: public Object execute(IAlgo algo, Object arg){ return _state.execute(algo, arg, this); } EmptyState: public O execute(IAlgo algo, LRStruct host, I arg) { return algo.emptyCase(host, arg); } NonEmptyState: public O execute(IAlgo algo, LRStruct host, I arg) { return algo.nonEmptyCase(host, arg); } LengthVisitor: public Integer emptyCase(LRStruct host, Object _) { return 0; // isn't autoboxing cool :-) } public Integer nonEmptyCase(LRStruct 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 arg (null) this algo arg (null) host this host _ (null) algo arg (null) this algo arg (null) host this host _ (null) 0 1 Driver: int len = list.execute(visitor, null); LRS: public Object execute(IAlgo algo, Object arg){ return _state.execute(algo, arg, this); } EmptyState: public O execute(IAlgo algo, LRStruct host, I arg) { return algo.emptyCase(host, arg); } NonEmptyState: public O execute(IAlgo algo, LRStruct host, I arg) { return algo.nonEmptyCase(host, arg); } LengthVisitor: public Integer emptyCase(LRStruct host, Object _) { return 0; // isn't autoboxing cool :-) } public Integer nonEmptyCase(LRStruct 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 arg (null) this algo arg (null) host this host _ (null) algo arg (null) this algo arg (null) host 0 1 Driver: int len = list.execute(visitor, null); LRS: public Object execute(IAlgo algo, Object arg){ return _state.execute(algo, arg, this); } EmptyState: public O execute(IAlgo algo, LRStruct host, I arg) { return algo.emptyCase(host, arg); } NonEmptyState: public O execute(IAlgo algo, LRStruct host, I arg) { return algo.nonEmptyCase(host, arg); } LengthVisitor: public Integer emptyCase(LRStruct host, Object _) { return 0; // isn't autoboxing cool :-) } public Integer nonEmptyCase(LRStruct 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 arg (null) this algo arg (null) host this host _ (null) algo arg (null) this 0 1 Driver: int len = list.execute(visitor, null); LRS: public Object execute(IAlgo algo, Object arg){ return _state.execute(algo, arg, this); } EmptyState: public O execute(IAlgo algo, LRStruct host, I arg) { return algo.emptyCase(host, arg); } NonEmptyState: public O execute(IAlgo algo, LRStruct host, I arg) { return algo.nonEmptyCase(host, arg); } LengthVisitor: public Integer emptyCase(LRStruct host, Object _) { return 0; // isn't autoboxing cool :-) } public Integer nonEmptyCase(LRStruct 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 arg (null) this algo arg (null) host this host _ (null) 0 1 Driver: int len = list.execute(visitor, null); LRS: public Object execute(IAlgo algo, Object arg){ return _state.execute(algo, arg, this); } EmptyState: public O execute(IAlgo algo, LRStruct host, I arg) { return algo.emptyCase(host, arg); } NonEmptyState: public O execute(IAlgo algo, LRStruct host, I arg) { return algo.nonEmptyCase(host, arg); } LengthVisitor: public Integer emptyCase(LRStruct host, Object _) { return 0; // isn't autoboxing cool :-) } public Integer nonEmptyCase(LRStruct 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 arg (null) this algo arg (null) host this host _ (null) Driver: int len = list.execute(visitor, null); LRS: public Object execute(IAlgo algo, Object arg){ return _state.execute(algo, arg, this); } EmptyState: public O execute(IAlgo algo, LRStruct host, I arg) { return algo.emptyCase(host, arg); } NonEmptyState: public O execute(IAlgo algo, LRStruct host, I arg) { return algo.nonEmptyCase(host, arg); } LengthVisitor: public Integer emptyCase(LRStruct host, Object _) { return 0; // isn't autoboxing cool :-) } public Integer nonEmptyCase(LRStruct 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 arg (null) this algo arg (null) host Driver: int len = list.execute(visitor, null); LRS: public Object execute(IAlgo algo, Object arg){ return _state.execute(algo, arg, this); } EmptyState: public O execute(IAlgo algo, LRStruct host, I arg) { return algo.emptyCase(host, arg); } NonEmptyState: public O execute(IAlgo algo, LRStruct host, I arg) { return algo.nonEmptyCase(host, arg); } LengthVisitor: public Integer emptyCase(LRStruct host, Object _) { return 0; // isn't autoboxing cool :-) } public Integer nonEmptyCase(LRStruct 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 value visitor arg (null) this Driver: int len = list.execute(visitor, null); LRS: public Object execute(IAlgo algo, Object arg){ return _state.execute(algo, arg, this); } EmptyState: public O execute(IAlgo algo, LRStruct host, I arg) { return algo.emptyCase(host, arg); } NonEmptyState: public O execute(IAlgo algo, LRStruct host, I arg) { return algo.nonEmptyCase(host, arg); } LengthVisitor: public Integer emptyCase(LRStruct host, Object _) { return 0; // isn't autoboxing cool :-) } public Integer nonEmptyCase(LRStruct host, Object _) { return 1 + host.getRest().execute(this, _); }
That’s it! Questions?
A variable used at runtime which was not explicitly declared in the program Used to hold the value returned by the recursive call, so that 1 can be added to it.
Variables: code vs. runtime In code, we declare instance variables once: public class Foo { private Bar _b; } In code, we declare parameters/local variables once: public int someFunction(int x, int y) { int z = x + y; return (z * x) / 2; } These names can represent many variables at runtime. Variable defined not just by name, but name and location in memory.
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.