Transcript Slide 1

Programming Language Concepts,
COSC-3308-01
Lecture 5
Iteration, Recursion, Exceptions, Type
Notation, and Design Methodology
7/18/2015
COSC-3308-01, Lecture 5
1
Reminder of the Last Lecture

Computing with procedures





lexical scoping
closures
procedures as values
procedure call
Introduction of



7/18/2015
properties of the abstract machine
last call optimization
full syntax to kernel syntax
COSC-3308-01, Lecture 5
2
Overview





Last Call Optimization
Recursion versus Iteration
Tupled Recursion
Exceptions
Type Notation


Constructing programs by following the type
Design methodology (standalone applications)
7/18/2015
COSC-3308-01, Lecture 5
3
Recursion: Summary

Iterative computations run in constant space

This concept is also called last call optimization

7/18/2015
no space needed for last call in procedure body
COSC-3308-01, Lecture 5
4
Power Function: Inductive Definition

We know (from school or university)
1
, if n is zero
x  xn-1
, n>0
xn =
7/18/2015
COSC-3308-01, Lecture 5
5
Recursive Function
fun {Pow X N}
if N==0 then 1
else X*{Pow X N-1}
end
end

Is this function using last call optimization
(a.k.a. tail-recursive)?


7/18/2015
not an iterative function
uses stack space in order of N
COSC-3308-01, Lecture 5
6
How Does Pow Compute?

Consider {Pow 5 3}, schematically:
{Pow 5 3}
5*{Pow 5 2}
5*(5*{Pow 5 1})
5*(5*(5*{Pow 5 0})))
5*(5*(5*1)))
5*(5*5)
5*25
125
7/18/2015
=
=
=
=
=
=
=
COSC-3308-01, Lecture 5
7
Better Idea for Pow

Take advantage of fact that multiplication can
be reordered (that is, a*(b*c)=c*(a*b))
{Pow
{Pow
{Pow
{Pow
5
5
5
5
3}*
2}*
1}*
0}*
1
(5*1)
(5*5)
(5*25)
1*125
=
= {Pow 5 2}*
5 =
= {Pow 5 1}* 25 =
= {Pow 5 0}* 125 =
= 125

Technique: accumulator for intermediate result
7/18/2015
COSC-3308-01, Lecture 5
8
Using Accumulators


Accumulator stores intermediate result
Finding an accumulator amounts to finding a
state invariant




A state invariant is a property (predicate) that is valid
on all states
State invariant must hold initially
A recursive call transforms one valid state into another
Final result must be obtainable from state invariant.
7/18/2015
COSC-3308-01, Lecture 5
9
So What Is the State for Pow
{Pow 5 3}* 1
{Pow 5 2}* (5*1)
{Pow 5 1}* (5*5)
(5, 3, 1)
(5, 2, 5)
(5, 1, 25)
{Pow 5 0}* (5*25) (5, 0, 125)

Technique: accumulator for intermediate result
7/18/2015
COSC-3308-01, Lecture 5
10
The PowAcc Function
fun {PowAcc X N Acc}
if N==0 then Acc
else {PowAcc X N-1 X*Acc}
end
end {PowerAcc X N Acc} = X^N * Acc
{PowerAcc X N-1 X*Acc} = X^(N-1)*(X*Acc)

Initial call is
{PowAcc X N 1}
{PowerAcc X N 1} = X^N
7/18/2015
COSC-3308-01, Lecture 5
11
Pow:
Complete Picture (PowA)
declare
local
fun {PowAcc X N Acc}
if N==0 then Acc
else {PowAcc X N-1 X*Acc}
end
end
in
fun {PowA X N} {PowAcc X N 1} end
end
 X and N are integers, because they are operands in
operations with 1.
7/18/2015
COSC-3308-01, Lecture 5
12
Pow:
Complete Picture (PowA)
declare
PowA
local
PowAcc
in
PowAcc = fun {$
if N==0 then
else {PowAcc
end
end
PowA = fun {$ X
end
7/18/2015
X N Acc}
Acc
X N-1 X*Acc}
N} {PowAcc X N 1} end
COSC-3308-01, Lecture 5
13
Is PowA() a Correct Function?

Actually, … no, because it doesn’t cover the
whole domain of integers …

7/18/2015
the call {PowA 2 ~4} will lead to an infinite loop
COSC-3308-01, Lecture 5
14
Characteristics of PowA

It has a tight scope, since PowAcc is visible only
to PowA




no other program could accidently use PowAcc
PowAcc belongs to PowA
Tight scope is important to conserve
namespace and avoid clash of identifiers.
Possible only very recently in…


7/18/2015
C++
“namespace” (took some twenty years)
Java “inner classes” (took a major language
revision)
COSC-3308-01, Lecture 5
15
Reverse

Reversing a list

How to reverse the elements of a list
{Reverse [a b c d]}
returns
[d c b a]
7/18/2015
COSC-3308-01, Lecture 5
16
Reversing a List

Reverse of nil is nil

Reverse of X|Xr is Z, where
reverse of Xr is Yr, and
append Yr and [X] to get Z
{Rev
{Rev
{Rev
{Rev
{Rev
[a b c d]}=
=[d c b a]
a|[b c d]}={Append {Rev [b c d]} [a]} =[d c b a]
b|[c d]}={Append {Rev [c d]} [b]}
=[d c b]
c|[d]}={Append {Rev [d]} [c]}
=[d c]
d|nil}={Append {Rev nil} [d]}
=[d]
nil
7/18/2015
COSC-3308-01, Lecture 5
17
Question

What is correct
{Append {Reverse Xr} X}
or
{Append {Reverse Xr} [X]}
7/18/2015
COSC-3308-01, Lecture 5
18
Naive Reverse Function
fun {NRev Xs}
case Xs of
nil then nil
[] X|Xr then {Append {NRev Xr} [X]}
end
end
7/18/2015
COSC-3308-01, Lecture 5
19
Question


What is the problem with the naive reverse?
Possible answers


not tail recursive
Append is costly:

there are O{|L1|} calls
fun {Append L1 L2}
case L1 of
nil then L2
[] H|T then H|{Append T L2}
end
end
7/18/2015
COSC-3308-01, Lecture 5
20
Cost of Naive Reverse

Suppose a recursive call {NRev Xs}


{Length Xs}=n
assume cost of {NRev Xs} is c(n)
where
number of function calls

then c(0) = 0
c(n) = c({Append {NRev Xr} [X]}) + c(n-1)
= (n-1) + c(n-1)
= (n-1) + (n-2) + c(n-2) =…= n-1 + (n-2) + … + 1


this yields: c(n) =
n( n  1)
2
For a list of length n, NRev uses approx. O(n2) calls!
7/18/2015
COSC-3308-01, Lecture 5
21
Doing Better for Reverse

Use an accumulator to capture currently
reversed list

Some abbreviations

{IR Xs}

Xs ++ Ys
7/18/2015
for {IterRev Xs}
for {Append Xs Ys}
COSC-3308-01, Lecture 5
22
Computing NRev
{NRev [a b c]}
{NRev [b c]}++[a]
({NRev [c]}++[b])++[a]
(({NRev nil}++[c])++[b])++[a]
((nil++[c])++[b])++[a]
([c]++[b])++[a]
[c b]++[a]
[c b a]
7/18/2015
COSC-3308-01, Lecture 5
=
=
=
=
=
=
=
23
Computing
{IR [a b c]
{IR [b c]
{IR [c]
{IR nil
[c b a]

IterRev (IR)
nil}
a|nil}
b|a|nil}
c|b|a|nil}
=
=
=
=
The general pattern:
{IR X|Xr Rs}  {IR Xr X|Rs}
7/18/2015
COSC-3308-01, Lecture 5
24
Why is Iteration Possible?
 Associative Property
{Append {Append RL [a]} [b]}
= {Append RL {Append [a] [b]}}
 More Generally
{Append {Append RL [a]} Acc}
= {Append RL {Append [a] Acc}}
= {Append RL a|Acc}
7/18/2015
COSC-3308-01, Lecture 5
25
IterRev
Intermediate Step
fun {IterRev Xs Ys}
case Xs of
nil then Ys
[] X|Xr then {IterRev Xr X|Ys}
end
end

Is tail recursive now
7/18/2015
COSC-3308-01, Lecture 5
26
IterRev
Properly Embedded
local
fun {IterRev Xs Ys}
case Xs
of nil then Ys
[] X|Xr then {IterRev Xr X|Ys}
end
end
in
fun {Rev Xs} {IterRev Xs nil} end
end
7/18/2015
COSC-3308-01, Lecture 5
27
State Invariant for IterRev

Unroll the iteration a number of times, we get:
{IterRev [x1 … xn] W}
=
{IterRev [xi+1 … xn] [xi … x1]++W}
7/18/2015
COSC-3308-01, Lecture 5
28
Reasoning for IterRev and Rev


Correctness:
{Rev Xs} is {IterRev Xs nil}
Using the state invariant, we have:
[x1 … xn] nil}=
{IterRev nil [xn … x1]}
[xn … x1]
{IterRev
=
=



Thus: {Rev [x1 … xn]}=[xn … x1]
Complexity:
The number of calls for {IterRev
list L has N elements, is c(N)=N
7/18/2015
COSC-3308-01, Lecture 5
L nil},
where
29
Summary So Far

Use accumulators




yields iterative computation
find state invariant
Loop = Tail Recursion and is a special case of
general recursion.
Exploit both kinds of knowledge


7/18/2015
on how programs execute
on application/problem domain
COSC-3308-01, Lecture 5
(abstract machine)
30
Tupled Recursion
Functions with multiple results
7/18/2015
COSC-3308-01, Lecture 5
31
Computing Average
fun {SumList Ls}
case Ls of nil then 0
[] X|Xs then X+{SumList Xs} end
end
fun {Length Ls}
case Ls of nil then 0
[] X|Xs then 1+{Length Xs} end
end
fun {Average Ls} {SumList Ls} div {Length Ls} end

What is the Problem?
7/18/2015
COSC-3308-01, Lecture 5
32
Problem?

Traverse the same list multiple times.

Solution: compute multiple results in a single
traversal!
7/18/2015
COSC-3308-01, Lecture 5
33
Tupling - Computing Two Results
fun {CPair Ls}
{Sum Ls}#{Length Ls}
end
fun {CPair Ls}
case Ls of nil then 0#0
[] X|Xs then case {CPair Xs}
of S#L then (X+S)#(1+L) end
end
end
7/18/2015
COSC-3308-01, Lecture 5
34
Using Tupled Recursion
fun {Average Ls}
{Sum Ls} div {Length Ls}
end
fun {Average Ls}
case {CPair Ls} of S#L then S div L end
end

Note: Division by zero should also be considered.
7/18/2015
COSC-3308-01, Lecture 5
35
Exceptions


An error is a difference between the actual behavior
of a program and its desired behavior.
Type of errors:




Internal: invoking an operation with an illegal type or illegal
value
External: opening a nonexisting file
We want detect these errors and handle them,
without stoping the program execution.
The execution is transferred to the exception
handler, and pass the exception handler a value
that describes the error.
7/18/2015
COSC-3308-01, Lecture 5
36
Exceptions handling






An Oz program is made up of interacting
“components” organized in hierarchical fashion.
The mechanism causes a “jump” from inside the
component to its boundary.
This jump should be a single operation.
The mechanism should be able, in a single operation,
to exit from arbitrarily many levels of nested contexts.
A context is an entry on the semantic stack, i.e., an
instruction that has to be executed later.
Nested contexts are created by procedure calls and
sequential compositions.
7/18/2015
COSC-3308-01, Lecture 5
37
Exceptions handling
7/18/2015
COSC-3308-01, Lecture 5
38
Exceptions (Example)
fun {Eval E}
if {IsNumber E} then E
else
case E
of plus(X Y) then {Eval X}+{Eval Y}
[] times(X Y) then {Eval X}*{Eval Y}
else raise illFormedExpression(E) end
end
end
end
try
{Browse {Eval plus(plus(5 5) 10)}}
{Browse {Eval times(6 11)}}
{Browse {Eval minus(7 10)}}
catch illFormedExpression(E) then
{Browse '*** Illegal expression '#E#' ***'}
end
7/18/2015
COSC-3308-01, Lecture 5
39
Exceptions (Example)
7/18/2015
COSC-3308-01, Lecture 5
40
Exceptions. try and raise



try: creates an exception-catching context together with
an exception handler.
raise: jumps to the boundary of the innermost
exception-catching context and invokes the exception
handler there.
try <s> catch <x> then <s>1 end:


if <s> does not raise an exception, then execute <s>.
if <s> raises an exception, i.e., by executing a raise
statement, then the (still ongoing) execution of <s> is aborted.
All information related to <s> is popped from the semantic stack.
Control is transferred to <s>1, passing it a reference to the
exception in <x>.
7/18/2015
COSC-3308-01, Lecture 5
41
Exceptions. Full Syntax

A try statement can specify a finally clause which is
always executed, whether the statement raises an
exception or not.

try <s>1 finally <s>2 end
is equivalent to:
 try <s>1
catch X then
<s>2
raise X end
end
<s>2
where an identifier X is chosen that is not free in <s>2
7/18/2015
COSC-3308-01, Lecture 5
42
Exceptions. Full Syntax (Example 1)
declare One Two
fun {One} 1 end
fun {Two} 2 end
try
{Browse a}
{One}={Two}
finally
{Browse b}
end
7/18/2015
declare One Two
fun {One} 1 end
fun {Two} 2 end
try
{Browse a}
{One}={Two}
catch X then
{Browse b}
raise X end
end
{Browse b}
COSC-3308-01, Lecture 5
43
How we catch that exception anyway?
declare One Two
fun {One} 1 end
fun {Two} 2 end
try
try
{Browse a}
{One}={Two}
catch X then
{Browse b}
raise X end
end
catch X then {Browse 'We caught the failure'}
end
{Browse b}
General idea: transform sequence of catch-s into nested catch-s.
7/18/2015
COSC-3308-01, Lecture 5
44
Exceptions. Full Syntax (Example 2)

It is possible to combine both catching the
exception and executing a finally statement.

try
{ProcessFile F}
catch X then
{Browse '*** Exception '#X#
' when processing file ***'}
finally {CloseFile F} end

It is similar with two nested try statements!
7/18/2015
COSC-3308-01, Lecture 5
45
System Exceptions




Raised by Mozart system
failure: attempt to perform an inconsistent
bind operation in the store (called also
“unification failure”);
error: run-time error inside a program, like
type or domain errors;
system: run-time condition in the environment
of the Mozart operation system process, like
failure to open a connection between two
Mozart processes.
7/18/2015
COSC-3308-01, Lecture 5
46
System Exceptions (Example)
functor
import
Browser
define
fun {One} 1 end
fun {Two} 2 end
try
{One}={Two}
catch
failure(...) then
{Browser.browse 'We caught the failure'}
end
end
7/18/2015
COSC-3308-01, Lecture 5
47
Type Notation
Constructing programs by following the type
7/18/2015
COSC-3308-01, Lecture 5
48
Dynamic Typing



Oz/Scheme uses dynamic typing, while Java uses
static typing.
In dynamic typing, each value can be of arbitrary
type that is only checked at runtime.
Advantage of dynamic types



no need to declare data types in advance
more flexible
Disadvantage


7/18/2015
errors detected late at runtime
less readable code
COSC-3308-01, Lecture 5
49
Type Notation

Every value has a type which can be
captured by:
e :: type


Type information helps program
development/documentation.
Many functions are designed based on the
type of the input arguments.
7/18/2015
COSC-3308-01, Lecture 5
50
Constructing Programs by Following
the Type



Programs so far take lists, hence they have a
form that corresponds to the list type:
List T ::= nil  T '|' List T
case Xs
of nil then expr1 % base case
[] X|Xr then expr2 % recursive call
end
7/18/2015
COSC-3308-01, Lecture 5
51
Constructing Programs by Following
the Type






This helps us when the type gets complicated
Nested lists are lists whose elements can be lists
Exercise: “Find the number of elements of a nested list”
Example: Xs= [[1 2] 4 nil [[5] 10]]
{NoElements Xs} = ?
{NoElements Xs} = 5
declare
Xs1=[[1 2] 4 nil]
{Browse Xs1}
 [[1 2] 4 nil]
Xs2=[[1 2] 4]|nil
{Browse Xs2}
 [[[1 2] 4]]
7/18/2015
COSC-3308-01, Lecture 5
52
Constructing Programs by Following
the Type



Nested lists
NList T ::= nil
 NList T '|' NList T
 T '|' NList T (T is neither nil nor a cons)
case Xs
of nil then expr1 % base case
[] X|Xr andthen {IsList X} then
expr2 % recursive calls for X and Xr
[] X|Xr then
expr3 % recursive call for Xr
end
7/18/2015
COSC-3308-01, Lecture 5
53
Constructing Programs by Following
the Type


Nested lists
Examples:

[[1 2] 3] is a nested list.


{NoElements [[1 2] 3]}={NoElements [1 2]} +
{NoElements [3]}=…
[1 2 3] is not a nested list (so, the number of elements
coincides with standard Oz function Length).
{NoElements [1 2 3]}=1+{NoElements [2 3]}=…
fun {IsList L}
L == nil orelse
{Label L}=='|' andthen {Width L}==2
end


7/18/2015
COSC-3308-01, Lecture 5
54
Constructing Programs by Following
the Type



Nested lists: fun {NoElements NList T}:Int
fun {NoElements Xs}
case Xs
of nil then 0 % base case
[] X|Xr andthen {IsList X} then
{NoElements X} + {NoElements Xr}
[] X|Xr then
1 + {NoElements Xr}
end
end
Question: What happens if the two case patterns
X|Xr are switched?
7/18/2015
COSC-3308-01, Lecture 5
55
Summary so far

Type Notation

7/18/2015
Constructing programs by following the type
COSC-3308-01, Lecture 5
56
Design methodology
Standalone applications
7/18/2015
COSC-3308-01, Lecture 5
57
Design methodology

“Programming in the large”


Written by more than one person, over a long
period of time
“Programming in the small”

7/18/2015
Written by one person, over a short period of time
COSC-3308-01, Lecture 5
58
Design methodology. Recommendations






Informal specification: inputs, outputs, relation
between them
Examples: mention particular cases
Exploration: determine the programming technique;
split the problem into smaller problems
Structure and coding: determine the program’s
structure; group related operations into one module
Testing and reasoning: test cases/formal semantics
Judging the quality: Is the design correct, efficient,
maintainable, extensible, simple?
7/18/2015
COSC-3308-01, Lecture 5
59
Software components


Split the program into logical units (also called
modules, components)
A logical unit has:


An interface = the visible part of the logical unit. It is
a record that groups together related languages
entities: procedures, classes, objects, etc.
An implementation = a set of languages entities
that are accessible by the interface operations but
hidden from the outside.
7/18/2015
COSC-3308-01, Lecture 5
60
Modules and module specifications


A module specification (software
component, functor) is a template that
creates a module (component instance)
each time it is instantiated.
In Oz, a functor is a function whose
arguments are the modules it needs and
whose result is a new module.

7/18/2015
Actually, the functor takes module interfaces as
arguments, creates a new module, and returns
that module’s interface!
COSC-3308-01, Lecture 5
61
Modules and module specifications




A software component is a unit of
independent deployment, and has no
persistent state.
Functors are a kind of software component.
A module is a component instance; it is the
result of installing a functor in a particular
module environment.
The module environment consists of a set of
modules, each of which may have an
execution state.
7/18/2015
COSC-3308-01, Lecture 5
62
Functors

A functor has three parts:




an import part = what other modules it needs
an export part = the module interface
a define part = the module implementation
including initialization code.
Functors in the Mozart system are
compilation units. That is, the system has
support for handling functors in files, both as:


7/18/2015
source code (i.e., human-readable text, .oz)
object code (i.e., compiled form, .ozf).
COSC-3308-01, Lecture 5
63
Standalone applications (1)




It can be run without the interactive interface.
It has a main functor, evaluated when the
program starts.
It imports the modules it needs, which causes
other functors to be evaluated.
Evaluating (or “installing”) a functor creates a
new module:



The modules it needs are identified.
The initialization code is executed.
The module is loaded the first time it is needed during
execution.
7/18/2015
COSC-3308-01, Lecture 5
64
Standalone applications (2)




This technique is called dynamic linking, as
opposed to static linking, in which the
modules are already loaded when execution
starts.
At any time, the set of currently installed
modules is called the module environment.
Any functor can be compiled to make a
standalone program.
So, no export part is necessary and the
initialization part defines the program’s effect.
7/18/2015
COSC-3308-01, Lecture 5
65
Functors. Example (GenericFunctor.oz)
functor
export generic:Generic
define
fun {Generic Op InitVal N}
if N == 0 then InitVal
else {Op N {Generic Op InitVal (N-1)}}
end
end
end
 The compiled functor GenericFunctor.ozf is created:
 ozc –c GenericFunctor.oz
7/18/2015
COSC-3308-01, Lecture 5
66
Functors. Example (GenericFact.oz)
functor
import
GenericFunctor
Browser
define
fun {Mul X Y} X*Y end
fun {FactUsingGeneric N}
{GenericFunctor.generic Mul 1 N}
end
{Browser.browse {FactUsingGeneric 5}}
end
 The executable functor GenericFact.exe is created:
 ozc –x GenericFact.oz
7/18/2015
COSC-3308-01, Lecture 5
67
Functors. Interactive Example
declare
[GF]={Module.link ['GenericFunctor.ozf']}
fun {Add X Y} X+Y end
fun {GenGaussSum N} {GF.generic Add 0 N} end
{Browse {GenGaussSum 5}}


The function Module.link is defined in the system
module Module.
It takes a list of functors, load them from the file system,
links them together


(i.e., evaluates them together, so that each module sees its
imported modules),
and returns a corresponding list of modules.
7/18/2015
COSC-3308-01, Lecture 5
68
Summary





Last Call Optimization
Recursion versus Iteration
Tupled Recursion
Exceptions
Type Notation


Constructing programs by following the type
Design methodology (standalone
applications)
7/18/2015
COSC-3308-01, Lecture 5
69
Reading suggestions

From [van Roy,Haridi; 2004]




7/18/2015
Chapter 2, Sections 2.4, 2.5, 2.6, 2.7
Exercises 2.9.4-2.9.12
Chapter 3, Sections 3.2-3.9
Exercises 3.10.6-3.10.17
COSC-3308-01, Lecture 5
70
Coming up next

Higher-Order Programming and Abstract
Data Types

7/18/2015
Chapter 3, Sections 3.2-3.9
COSC-3308-01, Lecture 5
71
Thank you for your attention!
Questions?
7/18/2015
COSC-3308-01, Lecture 5
72