Document 7826533

Download Report

Transcript Document 7826533

Declarative Programming Techniques
Non-declarative needs (VRH 3.8)
Program design in the small (VRH 3.9)
Carlos Varela
RPI
Adapted with permission from:
Seif Haridi
KTH
Peter Van Roy
UCL
C. Varela; Adapted w/permission from S. Haridi and P. Van Roy
1
Overview
•
What is declarativeness?
– Classification, advantages for large and small programs
•
Control Abstractions
– Iterative programs
•
Higher-order programming
– Basic operations, loops, data-driven techniques, laziness, currying
•
Modularity and non-declarative needs
– File and window I/O, large-scale program structure
•
•
Limitations and extensions of declarative programming
Lazy Evaluation
C. Varela; Adapted w/permission from S. Haridi and P. Van Roy
2
Software components
• What is a good way to organize a large program?
– It is confusing to put all in one big file
• Partition the program into logical units, each of which
implements a set of related operations
– Each logical unit has two parts, an interface and an implementation
– Only the interface is visible from outside the logical unit, i.e., from
other units that use it
– A program is a directed graph of logical units, where an edge
means that one logical unit needs the second for its implementation
• Such logical units are vaguely called « modules » or
« software components »
• Let us define these concepts more precisely
C. Varela; Adapted w/permission from S. Haridi and P. Van Roy
3
Basic concepts
• Module = part of a program that groups together related operations into
an entity with an interface and an implementation
• Module interface = a record that groups together language entities
belonging to the module
• Module implementation = a set of language entities accessible by the
interface but hidden from the outside (hiding can be done using lexical
scope)
• Module specification = a function whose arguments are module
interfaces, that creates a new module when called, and that returns this
new module’s interface
– Module specifications are sometimes called software components, but the
latter term is widely used with many different meanings
– To avoid confusion, we will call our module specifications functors and
we give them a special syntax (they are a linguistic abstraction)
C. Varela; Adapted w/permission from S. Haridi and P. Van Roy
4
Standalone applications
• A standalone application consists of one functor, called the
main functor, which is called when the application starts
– The main functor is used for its effect of starting the application
and not for the module it creates
– The modules it needs are linked dynamically (upon first use) or
statically (upon application start)
– Linking a module: First see whether the module already exists, if
so return it. Otherwise, find a functor specifying the module
according to some search strategy, call the functor, and link its
arguments recursively.
• Functors are compilation units, i.e., the system has support
for handling functors in files, in both source and compiled
form
C. Varela; Adapted w/permission from S. Haridi and P. Van Roy
5
Constructing a module
• Let us first see an example
of a module, and then we
will define a functor that
specifies that module
• A module is accessed
through its interface, which
is a record
• We construct the module
MyList
• MergeSort is inaccessible
outside the module
• Append is accessible as
MyList.append
declare MyList in
local
proc {Append …} … end
proc {MergeSort …} … end
proc {Sort …} … {MergeSort …} … end
proc {Member …} … end
in
MyList=‘export‘( append:Append
sort: Sort
member: Member
…)
end
C. Varela; Adapted w/permission from S. Haridi and P. Van Roy
6
Specifying a module
• Now let us define a functor
that specifies the module
MyList
• The functor MyListFunctor
will create a new module
whenever it is called
• The functor has no
arguments because the
module needs no other
modules
fun {MyListFunctor}
proc {Append …} … end
proc {MergeSort …} … end
proc {Sort …} … {MergeSort …} … end
proc {Member …} … end
in
‘export‘(append:Append
sort: Sort
member: Member
…)
end
C. Varela; Adapted w/permission from S. Haridi and P. Van Roy
7
Syntactic support for functors
•
•
•
•
We give syntactic support to the
functor
The keyword export is followed
by the record fields
The keyword define is followed
by the module initialization
code
There is another keyword not
used here, import, to specify
which modules the functor
needs
functor
export
append: Append
sort: Sort
member: Member
…
define
proc {Append …} … end
proc {MergeSort …} … end
proc {Sort …} … {MergeSort …} … end
proc {Member …} … end
end
C. Varela; Adapted w/permission from S. Haridi and P. Van Roy
8
Example standalone application
File Dict.oz
File WordApp.oz
functor
export
new:NewDict put:Put
condGet:CondGet entries:Entries
define
fun {NewDict} ... end
fun {Put Ds Key Value} … end
fun {CondGet Ds Key Default} … end
fun {Entries Ds} … end
end
functor
import Open Dict QTk
define
… (1. Read stdin into a list)
… (2. Calculate word frequencies)
… (3. Display result in a window)
end
•
•
Compile Dict.oz giving
Dict.ozf
Compile WordApp.oz giving
WordApp*
C. Varela; Adapted w/permission from S. Haridi and P. Van Roy
9
Library modules
• A programming system usually comes with many modules
– Built-in modules: available without needing to specify them in a
functor
– Library modules: have to be specified in a functor
C. Varela; Adapted w/permission from S. Haridi and P. Van Roy
10
Non-declarative needs
• Example modules exist for non-declarative needs, e.g.:
– File I/O
– Graphical User Interfaces
C. Varela; Adapted w/permission from S. Haridi and P. Van Roy
11
Large-scale program structure
• Modules: an example of higher-order programming
• Module specifications
C. Varela; Adapted w/permission from S. Haridi and P. Van Roy
12
Limitations and extensions
of declarative programming
• Is declarative programming expressive enough to do everything?
– Given a straightforward compiler, the answer is no
• Examples of limitations: File I/O, GUI.
• Extensions of declarative programming:
– Concurrency
– State
– Concurrency and state
• When to use each model
– Use the least expressive model that gives a simple program (without
technical scaffolding)
– Use declarative whenever possible, since it is by far the easiest to reason
about, both in the small and in the large
C. Varela; Adapted w/permission from S. Haridi and P. Van Roy
13
Lazy evaluation
• The functions written so far are evaluated eagerly (as soon
as they are called)
• Another way is lazy evaluation where a computation is
done only when the results is needed
• Calculates the infinite list:
0 | 1 | 2 | 3 | ...
declare
fun lazy {Ints N}
N|{Ints N+1}
end
C. Varela; Adapted w/permission from S. Haridi and P. Van Roy
14
Lazy evaluation (2)
• Write a function that computes as
many rows of Pascal’s triangle as
fun lazy {PascalList Row}
needed
Row | {PascalList
{AddList
• We do not know how many
{ShiftLeft Row}
beforehand
{ShiftRight Row}}}
• A function is lazy if it is evaluated
end
only when its result is needed
• The function PascalList is evaluated
when needed
C. Varela; Adapted w/permission from S. Haridi and P. Van Roy
15
Lazy evaluation (3)
• Lazy evaluation will avoid
redoing work if you decide first
you need the 10th row and later
the 11th row
• The function continues where it
left off
declare
L = {PascalList [1]}
{Browse L}
{Browse L.1}
{Browse L.2.1}
L<Future>
[1]
[1 1]
C. Varela; Adapted w/permission from S. Haridi and P. Van Roy
16
Exercises
•
•
•
Use the File I/O module in Oz to create a program that
reads a file and and writes the word that occurs more
frequently in the file.
Create a Stack module and an example program using the
module.
Read VRH Section 4.5.
C. Varela; Adapted w/permission from S. Haridi and P. Van Roy
17