Note that the preceding, object-oriented, definition still gives us an immutable list class: None of the methods cause the list value to change.
In some applications, we might want to be able to change the list object in place. For example, we could add new elements to the list, and all code using that list would see the effect of the modification.
This is quite a different style of programming from the purely functional one, and one must be very careful in treating lists in this way; we cannot share such lists freely and expect there value to be unchanged. For this reason, we call these lists
"Closed Lists"
despite the fact that we can do most of the things with them that we did with open lists.
The closed class could have all of the methods previously introduced, but add ones which exploit the mutable nature.
An example of a method for the new class might be "push", which adds a new element to the front end and pop which removes the first thing on the list.
class ClosedStringList { StringCell handle; // pointer to the first cell in the list ClosedStringList() // create new empty modifiable list { handle = null; } String first() // return the first element of the list { return handle.first; } ClosedStringList rest() // return the rest of the list { return new ClosedStringList(handle.rest); } boolean isEmpty() // check for emptiness { return handle == null; } // create new list given first and rest static ClosedStringList cons(String first, ClosedStringList rest) { return new ClosedStringList(new StringCell(first, rest.handle)); } // create new list with first and this as rest ClosedStringList cons(String first) { return cons(first, this); } ClosedStringList(StringCell handle) { this.handle = handle; } // note that nil != null final static ClosedStringList nil = new ClosedStringList(null); // mutating methods for Stack // add a new first element to list, destructively changing this void push(String s) { handle = new StringCell(s, handle); } // remove first element and return it, destructively changing this String pop() { String top = first(); handle = rest().handle; return top; }// StringCell is the building block for ClosedStringList class StringCell { String first; StringCell rest; StringCell(String first, StringCell rest) { this.first = first; this.rest = rest; } }
Push and pop render the list capable of being used as a data abstraction known as a Stack, as these operations are the defining characteristics of this class.
A closed list S, to be used as a Stack
The above closed list S, after pop()
The above closed list S, after push(e)
The empty stack
Link to ClosedStringList.java, a complete file illustrating these ideas.
Next Slide | Previous Slide | Contents |