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.