This preview shows pages 1–3. Sign up to view the full content.
This preview has intentionally blurred sections. Sign up to view the full version.
View Full Document
Unformatted text preview: 198 Declarative Programming Techniques 3.7.1 A declarative stack To start this section, let us give a simple example of an abstract data type, a stack Stack T whose elements are of type T . Assume the stack has four operations, with the following types: fun {NewStack}: Stack T fun {Push Stack T T }: Stack T fun {Pop Stack T T }: Stack T fun {IsEmpty Stack T }: Bool This set of operations and their types defines the interface of the abstract data type. These operations satisfy certain laws: • {IsEmpty {NewStack}} = true . A new stack is always empty. • For any E and S0 , S1={Push S0 E} and S0={Pop S1 E} hold. Pushing an element and then popping gives the same element back. • {Pop {EmptyStack}} raises an error. No elements can be popped off an empty stack. These laws are independent of any particular implementation, or said differently, all implementations have to satisfy these laws. Here is an implementation of the stack that satisfies the laws: fun {NewStack} nil end fun {Push S E} ES end fun {Pop S E} case S of XS1 then E=X S1 end end fun {IsEmpty S} S==nil end Here is another implementation that satisfies the laws: fun {NewStack} stackEmpty end fun {Push S E} stack(E S) end fun {Pop S E} case S of stack(X S1) then E=X S1 end end fun {IsEmpty S} S==stackEmpty end A program that uses the stack will work with either implementation. This is what we mean by saying that stack is an abstract data type. A functional programming look Attentive readers will notice an unusual aspect of these two definitions: Pop is written using a functional syntax, but one of its arguments is an output! We could have written Pop as follows: fun {Pop S} case S of XS1 then X#S1 end end which returns the two outputs as a pair, but we chose not to. Writing {Pop S E} is an example of programming with a functional look , which uses functional syntax for operations that are not necessarily mathematical functions. We consider that Copyright c 20013 by P. Van Roy and S. Haridi. All rights reserved. 3.7 Abstract data types 199 fun {NewDictionary} nil end fun {Put Ds Key Value} case Ds of nil then [Key#Value] (K#V)Dr andthen Key==K then (Key#Value)  Dr (K#V)Dr andthen K>Key then (Key#Value)(K#V)Dr (K#V)Dr andthen K<Key then (K#V){Put Dr Key Value} end end fun {CondGet Ds Key Default} case Ds of nil then Default (K#V)Dr andthen Key==K then V (K#V)Dr andthen K>Key then Default (K#V)Dr andthen K<Key then {CondGet Dr Key Default} end end fun {Domain Ds} {Map Ds fun {$ K#_} K end } end Figure 3.27: Declarative dictionary (with linear list) this is justified for programs that have a clear directionality in the flow of data. It can be interesting to highlight this directionality even if the program is not functional. In some cases this can make the program more concise and more readable. The functional look should be used sparingly, though, and only in cases where it is clear that the operation is not a mathematical function. We will use the functional look occasionally throughout the book, when we judge it...
View
Full
Document
This document was uploaded on 08/10/2011.
 Spring '11

Click to edit the document details