Introduction to Oz and the Mozart System

Download Report

Transcript Introduction to Oz and the Mozart System

Lecture 2: Basic Control and Procedures
Per Brand
1
Basic Control Structures
• Sequence of statements:
S1 S2
• The thread executes statements in a sequential order.
However a thread, contrary to conventional languages,
may suspend in some statement, so above a thread has to
complete execution of S1, before starting S2.
• Empty statement:
skip
2
If Statement
• Oz provides a simple form of conditional statement having
the following form:
if B then S1 else S2 end
– B should be a Boolean value.
• Semantics
– If B is bound to true S1 is executed
– if B is bound to false S2 is executed
– if B is bound to an non-Boolean value, an exception is
raised
– otherwise if B is unbound the thread suspends until one
of the cases above applies
3
Comparison Procedures
• Oz provides a number of built-in tertiary procedures These
include == that we have seen earlier as well as \=, =<, <,
>=, and >.
• Used as Boolean functions in an infix notation.
• In this example Z is bound to the maximum of X and Y,
i.e. to Y:
declare X Y Z
X = 5
Y = 10
if X >= Y then Z = X else Z = Y end
4
Abbreviations
• A statement using the keyword elseif:
if B1 then S1 elseif B2 then S2 else S3 end
• is shorthand for nested if-statements:
if B1 then S1
else if B2 then S2
else S3 end
end
• An if-statement missing the else part:
if B1 then S1 end
• is equivalent to:
• if B1 then S1 else skip end
5
Procedure Abstractions
• A procedure in Oz is a first class value:
– can be defined.
declare
proc {P X1 … Xn} S end
– can be applied
{P Y1 … Yn}
– passed around as argument to another procedure, e.g..
{Q P 1}
– and, stored in an arbitrary data-structure, e.g. record.
X=rec(P)
6
Procedure Definition & Application
• By example
declare Max X Y Z
proc {Max X Y Z}
if X >= Y then
Z = X
else Z = Y end
end
X = 5 Y = 10
{Max X Y Z}
{Show Z} %% shows 10
7
Procedures cont’d
• Procedures don’t return anything directly
• Return achieved by using single-assignment variables as
parameters
– e.g. {Max In1 In2 Return}
• More general as procedures can ‘return’ multiple values
declare Two F S
proc {Two In First Second}
First=In.1
Second= In.2
end
{Two f(a b) F S} % F is bound to a, S to b
8
Procedures cont’d
• Observe convention
– put the output parameter(s) at the end
• Very often there is one and exactly one return value
– Oz supports functional declaration as syntactic sugar
– Recommendation: use it for pure functions
fun {Max X Y}
if X >= Y then X
else Y
end
end
proc{Max X Y Aux}
if X >= Y then Aux=X
else Aux=Y
end
end
9
Functions
fun{Max X Y}
if X >= Y then
X
else
Y
end
end
proc{Max X Y Aux}
if X >= Y then
Aux=X
else
Aux=Y
end
end
Max
X>=Y
X
Y
Control ends in expression
and not statement
10
More syntactic sugar
fun{Max X Y}
if X >= Y then X
else Y
end
end
declare A
A={Max 1 3}
{Show A}
%% or
{Show {Max 1 3 $}}
%% or
{Show {Max 1 3}}
%% shows 3
%% shows 3
%% shows 3
11
Procedures are first class
• Procedures and everything else in Oz are first class
• declare Max Rec
Rec= rec(1 2)
Max= proc {$ X Y Z}
if X >= Y then
Z = X
else Z = Y end
end
• Max is bound to the procedure
• Rec is bound to the record
12
1st class
• Procedures and everything else in Oz are first class
• declare Max
Max= proc {$
if X
Z
else
end
X Y Z}
>= Y then
= X
Z = Y end
• Max is bound to the procedure
• The procedure is in the store just like other data structures
• What can you do with Max??
– Usual stuff
– Apply it
– But more !!!
13
Equality
• Equality and equality test - token or pointer equality
– records, numbers etc. have structural equality
• declare
fun {Max X Y}
if X >= Y then Z
else Y end
end
fun {Max2 X Y}
if X >= Y then Z
else Y end
end
fun {Min X Y}
if X >= Y then Y
else Z end
end
Alias=Max
{Show Max==Min} %% shows false
{Show Max==Max2} %% shows false
{Show Max==Alias} %% shows true
14
Example: procedures as parameters
declare A B
proc {Twice Inc In Out}
local Aux in
{Inc In Aux}
{Inc Aux Out}
end
end
proc {Inc1 In Out}
Out= In+1
end
proc {Inc2 In Out}
Out= s(In)
end
{Twice Inc1 1 A}
{Twice Inc2 s(0) B}
{Show A#B}
%% shows 3#s(s(s(0)))
15
Example: procedures in data structure
declare
fun{Max A B}
…
end
fun {Min A B}
…
end
MyMathModule=math(max:Max min:Min)
declare Max Min
{MyMathModule.max 1 3 Max}
{MyMathModule.min 1 3 Min}
{Show Max#Min} %% 3#1
16
Example: procedures returning
procedures
declare P1 P2
fun {GenInc2 Inc}
fun{$ A}
{Inc {Inc A}}
end
end
P1={GenInc2 fun{$ A} A+1 end}
{Show {P1 5}} %%% Shows 7
P2={GenInc2 fun{$ A} s(s(A)) end}
{Show {P2 (s(0)}} %%% Shows s(s(s(0)))
17
Lexical Scoping
• In the statement S some variable occurrences are syntactically bound
while others are free.
• A variable occurrence X in S is bound:
– If X is in the scope of the procedure formal-parameter X.
– Or is in the scope of a variable introduction statement, or other
variable-binding construct, that introduces X.
– Otherwise, the identifier occurrence is free.
• Each free variable occurrence in an program is eventually bound by the
closest textually surrounding identifier-binding construct.
• Lexical (static) scoping: when free variables in procedure, function, or a
class are bound at their definition position by the nearest enclosing
definition
• Dynamic scoping otherwise, at the context of call, or location of a call18
Semantics: proc
{P X1 … Xn} S end
 The variable P should be already introduced.
 Executing the above statement will create a procedure (closure):
an abstraction: (X1 … Xn).S.
 P is bound to the closure.
 A closure contains
 code
 references to those entities referenced by the free variables in
the procedure.
19
Closures
 (X1 … Xn).S.
 Assume Y1 … Yn occures free in S.
Y1
Y1
:
:
Environment
Yn
Yn
Code
for S
20
Example: procedures returning
procedures revisited
declare
proc{GenMax Less Aux1}
Aux1=proc{$ A B Aux2}
if {Less A B} then Aux2=B %% in closure
else Aux2=A end
end
end
P={GenMax fun{$ A B} A<B end}
Q={GenMax fun{$ A B} … end}
Closure of Aux1 contains the procedure Less
21
Example: closure containing data
declare Mod
proc{MyMath Out}
local Pi A C in
Pi=3.14159
Out=math(area:A circ:C)
A=fun{$ Rad} Pi*Rad*Rad
B=fun{$ Rad} 2.0*Pi*Rad
end
end
{MyMath Mod}
{Show {Mod.area 3.0}#{Mod.circ 3.0}}
22
Closures
• Closures contain code + arbitrary entites
• Most common
– other procedures
– stateful entities (dealt with in a later lecture)
23
Anonymous Procedures and Variable
Initialization
• Why is a variable bound to a procedure in a way that is different from
the variable being bound to record:
• X = Value?
• What you see is just a syntactic variant of the equivalent form:
P = proc {$ X1 … Xn} S end
• The R.H.S. defines an anonymous procedural value.
(X1 … Xn).S
24
variable-initialization equality
•
Variables could be introduced and initialized simultaneously by:
X = OzValue or Record = OzValue
• between local and in, in a statement of the form:
local ... in ... end.
local
Max = proc {$ X Y Z}
if X >= Y then Z = X else Z = Y end
end
X = 5 Y = 10
Z
in
{Max X Y Z} {Show Z}
end
25
Variable-initialization equality
•
Only the variables occurring on the L.H.S. of the equality are the ones
being introduced
• local
Y = 1
in
local
M = f(M Y)
[X1 Y] = L
L = [1 2]
in
{Show M} %% shows f(f(…) 2)
end
end
•
The outer variable Y is invisible in the innermost: local ... end
statement.
26
Variable-initialization equality
• local
Y = 1
in
local
M = f(M Y)
[Z Y] = L
L = [1 2]
in
{Show M}
end
end
• local Y in
Y = 1
local M X1 Y L in
M = f(M Y)
L = [Z Y]
L = [1 2]
{Show M}
end
end
27
The exclamation mark ‘!’
• Used to suppress variable introduction.
• An exclamation mark ‘!’ is only meaningful in the L.H.S. of an
initializing equality and in pattern matching constructs.
local
Y = 1
in
local
M = f(M Y)
[X1 !Y] = L
L = [1 2]
in
{Show M}
end
end
• local Y in
Y = 1
local M X1 L in
M = f(M Y)
L = [X1 Y]
L = [1 2]
{Show M}
end
end
28
Variable declaration abbreviation
local X in S end
X in S
often abbreviated
proc{MyMath Out}
Pi A C in
Pi=3.14159
Out=math(area:A circ:C)
A=fun{$ Rad} Pi*Rad*Rad
B=fun{$ Rad} 2.0*Pi*Rad
%% implicit end here
end
29
Pattern Matching
• Case Statement
• case E of
Pattern1 then S1
[] Pattern2 then S2
[] ...
else S end
• All variables introduced in Patterni are implicitly declared, and have a
scope stretching over the corresponding Si.
30
Pattern Matching Semantics
• E is evaluated to V.
•
Executing the case statement will sequentially match V against the patterns
Pattern1, Pattern2, ...,Patternn in this order.
•
Matching V against Patterni is done in left-to-right depth-first manner.
•
If V matches Patterni without binding any variable occuring in V, the
corresponding Si statement is executed.
•
If V matches Patterni but binds some variables occuring in V, the thread
suspends
•
If the matching of V and Patterni fails, V is tried against the next pattern
Patterni+1, otherwise the else statement S is executed.
•
The else part may be omitted, in which case an exception is raised if all
matches fail.
•
Suppressing the introduction of a new local variable by using !. For example, in
the following example:
– case f(X1 X2) of f(!Y Z) then ... else ... end
31
Case for pattern matching
• proc {Insert Key Value TreeIn ?TreeOut}
case TreeIn
of nil then TreeOut = tree(Key Value nil nil)
[] tree(K1 V1 T1 T2) then
if Key == K1 then
TreeOut = tree(Key Value T1 T2)
elseif Key < K1 then T in
TreeOut = tree(K1 V1 T T2)
{Insert Key Value T1 T}
else T in
TreeOut = tree(K1 V1 T1 T)
{Insert Key Value T2 T}
end
end
end
32
Nesting
•
Intermediate variables are introduced
• local T0 T1 T2 T3 in
{Insert a 3 nil T0}
{Insert b 15 T0 T1}
{Insert c 10 T1 T2}
{Insert d 7 T2 T3}
end
•
Oz provides syntactic support for nesting one procedure calls inside another
– local Y in
{P ... Y ...}
{Q Y ... }
end
•
could be written as:
–
•
{Q {P ... $ ...} ... }
using ‘$’ as a nesting marker.
33
Functional Nesting
•
A procedure {P X … R} is a function; its result is the argument R.
• {P X …} is a function call that can be inserted in any expression instead of
the result argument.
{Q {P X … } … } is equivalent to:
local R in
{P X ... R}
{Q R ... }
end
Our example, a more concise form using functional nesting is:
•
{Insert d 7
{Insert c 10
{Insert b 15 {Insert a 3 nil}}}}}
34
Nested Application
•
Nested application inside a record or a tuple:
Zs = X|{SMerge Xr Ys $}
•
The nested application goes after the record construction statement.
local Zr in
Zs = X|Zr
{SMerge Xr Ys Zr}
end
35
Example - merging two sorted lists
proc {SMerge Xs Ys Zs}
case Xs#Ys
of nil#Ys then Zs=Ys
[] Xs#nil then Zs=Xs
[] (X|Xr) # (Y|Yr) then
if X=<Y then
Zs = X|{SMerge Xr Ys $}
else Zr in
Zs = Y|{SMerge Xs Yr $}
end
end
end
36
Procedures as Values
•
The procedure BinaryTree checks a structure to verify whether it is a
binary tree or not, and accordingly returns true or false in its result
argument B.
% What is a binary tree?
local
proc {And B1 B2 ?B}
if B1 then B = B2 else B = false end
end
in
proc {BinaryTree T ?B}
case T
of nil then B = true
[] tree(K V T1 T2) then
{And {BinaryTree T1}
{BinaryTree T2} B}
else B = false end
end
end
37
Problem and Fix
The call
{And {BinaryTree T1}{BinaryTree T2} B}
is certainly doing unnecessary work.
According to our nesting rules, it evaluates its
2nd argument even if the first is false.
38
Problem & Fix
•
•
The call {And {BinaryTree T1}{BinaryTree T2} B} may be doing
unnecessary work.
– According to our nesting rules, it evaluates its 2nd argument even if the first
is false.
Define new procedure AndThen:
– It takes as its first two arguments two procedures, and calls the second
procedure only if the first returns false.
– The procedure is another example of a higher-order procedure:
– fun{AndThen A B}
if A then B
else false
end
39
Control Abstractions
• Higher-order procedures are used in Oz to define various control
abstractions.
In modules Control and List as well as many others, you will find
many control abstractions.
• Syntactic support for iterators
• for <iterators> do <S> end
• where iterators are
– X in L
%% iterates over the list L
– X in I..J
%% iterates over the integers I to J, inclusive
– X in I..J; K
%% iterates over the integers I to J, inclusive
with increments of K
40
More higher order procedures
proc {ForAll Xs P}
case Xs
of nil then skip
[] X|Xr then
{P X}
{ForAll Xr P}
end
end
{ForAll [1 2 3] Show}
%%%% or use the below
for X in [1 2 3] do Show end
41
Example - iteration
local
proc {HelpPlus C To Step P}
if C=<To then
{P C} {HelpPlus C+Step To Step P}
end
end
proc {HelpMinus C To Step P}
if C>=To then
{P C} {HelpMinus C+Step To Step P}
end
end
in
proc {For From To Step P}
if Step>0 then {HelpPlus From To Step P}
else {HelpMinus From To Step P} end
end
end
{For 3 7 2 proc{$ X} {Show X} end}
%% or
for X in 3..7;2 do {Show X} end
42