Re: OOP experiments in Mathematica- The Stack
- To: mathgroup at smc.vnet.net
- Subject: [mg38657] Re: OOP experiments in Mathematica- The Stack
- From: "Steve S. Shaw" <steve at shawstudio.com>
- Date: Fri, 3 Jan 2003 00:16:04 -0500 (EST)
- Sender: owner-wri-mathgroup at wolfram.com
A series of OOP experiments in Mathematica. msg#2 - The Stack, part#2: a simple Eiffel implementation of a stack. Discussion: I'm not sure how useful this is to anyone not familiar with Eiffel - without a lengthy explanation. But in general, Eiffel is closest to the features I desire, so I expect to show a fair number of Eiffel examples. I'll try to show each example in Java as well - though that won't always be possible. Important features of the Eiffel code: 1. The functions and the preconditions are specified in a "deferred class", Z_STACK. This would be an "abstract class" in C++; an "interface" in Java. The Eiffel compiler guarantees that any implementing class correctly matches this specification. (Any violation of preconditions is caught at run-time.) If a client only refers to the deferred class, then a different implementing class can easily be substituted. Well, some code somewhere has to know the implementing class, to create new objects. But that code can be localized ("Factory Pattern"), then all other code is independent of chosen implementation. For example, HELLO has the declaration "s1: Z_STACK" which is referring to the abstract "deferred class". 2. The implementing class "APPEND_STACK" stores items in a LINKED_LIST. Each pushed item is appended to the end of the list. 3. Eiffel "Base" class library already has a "STACK" class, which I am deliberately not using in this example. 4. "HELLO.make" is the entry point to this example. It produces the output shown way below. ----------------------------------------------------------------- indexing description: "Abstract Protocol for all stacks (elements not typed)" author: "ToolmakerSteve at ShawStudio.com" date: "31-Dec-2002" revision: "1.0.0" deferred class Z_STACK feature -- Access -- NO, don't actually have this feature. -- Instead, client ("HELLO") will use Eiffel's syntax for creating an object. --new: Z_STACK is -- -- create empty instance -- deferred -- end is_empty: BOOLEAN is deferred end top: ANY is -- most recently pushed item require not is_empty deferred end feature -- Element change push( item: ANY ) is -- store item without forgetting previous items deferred end drop is require not is_empty deferred end feature -- Compound Action pop: ANY is -- return top, and drop it from stack. require not is_empty do result := top drop end invariant invariant_clause: True -- Your invariant here end -- class Z_STACK ----------------------------------------------------------------- indexing description: "Concrete Implementation of stack (elements not typed)" author: "ToolmakerSteve at ShawStudio.com" date: "31-Dec-2002" revision: "1.0.0" class APPEND_STACK inherit Z_STACK redefine default_create end; feature {NONE} -- Initialization default_create is -- Initialize `Current'. do -- TBD: Suppose client wants different concrete type, -- for different performance characteristics? !!items.make() end feature -- Access --new: Z_STACK is -- -- create empty instance of this type. -- do -- !APPEND_STACK!result -- end top: ANY is -- most recently pushed item do --result := items.first -- deliberate mistake to test axioms result := items.last end feature -- Status report is_empty: BOOLEAN is do result := items.is_empty end feature -- Element change push( item: ANY ) is -- store item without forgetting previous items do items.force( item ); end drop is do -- YUK. Have to do cursor movement just to delete last item. items.finish -- points TO last item, not past it! items.remove end feature {NONE} -- Implementation items: LINKED_LIST [ANY] -- holds pushed items invariant items_not_void: items /= Void end -- class APPEND_STACK ----------------------------------------------------------------- indexing description : "System's root class" class HELLO creation make feature -- Initialization make is -- Creation procedure. local s1: Z_STACK do print( "Hello.%N" ); !APPEND_STACK!s1 print( "new stack s1%N" ); print_top_or_empty( s1 ); s1.push( "x1" ); print( "push x1.%N" ); print_top_or_empty( s1 ); s1.push( "x2" ); print( "push x2.%N" ); print_top_or_empty( s1 ); s1.drop; -- drop x2 print( "drop.%N" ); print_top_or_empty( s1 ); --s1.drop; -- drop x1 --print( "drop.%N" ); print( "pop: " ); print( s1.pop ); print( "%N" ); print_top_or_empty( s1 ); print( "Goodbye.%N" ); end feature {NONE} -- Implementation print_top_or_empty( s1: Z_STACK ) is -- if s1 empty then say so else print its top item. do if s1.is_empty then print( "--s1 is empty--%N" ); else print( "--s1.top: " ); print( s1.top ); print( "%N" ); end end end -- class HELLO ----------------------------------------------------------------- ----- Output from running "HELLO" ----- Hello. new stack s1 --s1 is empty-- push x1. --s1.top: x1 push x2. --s1.top: x2 drop. --s1.top: x1 pop: x1 --s1 is empty-- Goodbye.