83
03/26/22 COSC-3308-01, Lecture 6 1 Programming Language Concepts, COSC-3308- 01 Lecture 6 Higher-Order Programming and Abstract Data Types

5/15/2015COSC-3308-01, Lecture 61 Programming Language Concepts, COSC-3308-01 Lecture 6 Higher-Order Programming and Abstract Data Types

Embed Size (px)

Citation preview

04/18/23 COSC-3308-01, Lecture 6 1

Programming Language Concepts, COSC-3308-01Lecture 6  

Higher-Order Programming and Abstract Data Types

04/18/23 COSC-3308-01, Lecture 6 2

Reminder of the Last Lecture

Last call optimization Recursion versus Iteration Tupled recursion Exceptions Type notation Design methodology

04/18/23 COSC-3308-01, Lecture 6 3

Overview

Higher-order programming Abstract data types October 22, Friday – 9:00am-10:00am

Mid-term exam (20% of the final grade) Lectures 1-5, Tutorials 1-4

04/18/23 COSC-3308-01, Lecture 6 4

Higher-Order Programming

04/18/23 COSC-3308-01, Lecture 6 5

Higher-Order Programming

Higher-order programming = the set of programming techniques that are possible with procedure values (lexically-scoped closures).

Higher-order programming is the foundation of secure data abstraction component-based programming and object-oriented programming.

04/18/23 COSC-3308-01, Lecture 6 6

Higher-Order Programming A procedure which has no procedures as

arguments is called first-order. A procedure which has at least one procedure

as argument is called second-order … A procedure is of order n+1 if it has at least

one argument of order n and none of higher order.

Higher-order programming procedures can be of any order.

04/18/23 COSC-3308-01, Lecture 6 7

Remember (I)

Functions are procedures Special syntax, nested syntax, expression syntax They are procedures with one argument as the

result arguments Example:fun {F X} fun {$ Y} X+Y endend

A function that returns a function that is specialized on X

04/18/23 COSC-3308-01, Lecture 6 8

Remember (II)

Successive transformations to procedures1. fun {F X}

fun {$ Y} X+Y endend

2. proc {F X ?R} R = fun {$ Y} X+Y endend

3. proc {F X ?R} R = proc {$ Y ?R1} R1=X+Y endend

04/18/23 COSC-3308-01, Lecture 6 9

Remember (III)3. proc {F X ?R}

R = proc {$ Y ?R1} R1=X+Y endend

F is a procedure value When F is called, its 2nd argument returns a

procedure value ‘?’ is comment indicating output argument

04/18/23 COSC-3308-01, Lecture 6 10

Remember (IV)

declare

fun {F X}

fun {$ Y} X+Y end

end

{Browse F}

G={F 1}

{Browse G}

{Browse {G 2}}

F is a function of one argument, which corresponds to a procedure having two arguments

<P/2 F> G is an unnamed function

<P/2> {G Y} returns 1+Y

3

04/18/23 COSC-3308-01, Lecture 6 11

Remember (V)1. fun {F X}

fun {$ Y} X+Y endend

The type of F fun {F Num}:

fun {$ Num}: Num

04/18/23 COSC-3308-01, Lecture 6 12

Higher-Order Programming

Basic operations: Procedural abstraction: the ability to convert

any statement into a procedure value Genericity: the ability to pass procedure values

as arguments to a procedure call Instantiation: the ability to return procedure

values as results from a procedure call Embedding: the ability to put procedure values

in data structures

04/18/23 COSC-3308-01, Lecture 6 13

Higher-Order Programming

Control abstractions The ability to define control constructs Integer and list loops, accumulator loops,

folding a list (left and right)

04/18/23 COSC-3308-01, Lecture 6 14

Procedural Abstraction

Procedural abstraction is the ability to convert any statement into a procedure value.

Statement

Normal Execution

time

P = proc{$} Statement end

{P}

Delayed Execution

time

04/18/23 COSC-3308-01, Lecture 6 15

Procedural Abstraction A procedure value is usually called a closure,

or more precisely, a lexically-scoped closure A procedure value is a pair: it combines the

procedure code with the contextual environment Basic scheme:

Consider any statement <s> Convert it into a procedure value: P = proc {$} <s> end

Executing {P} has exactly the same effect as executing <s>

04/18/23 COSC-3308-01, Lecture 6 16

The Same Holds for Expressions A procedure value is usually called a closure, or more precisely, a lexically-scoped closure A procedure value is a pair: it combines the

procedure code with the contextual environment Basic scheme:

Consider any expression <E>, embedded in an equality like X = E

Convert it into a function value: F = fun {$} <E> end

Executing X = {F} has exactly the same effect as executing X = E

04/18/23 COSC-3308-01, Lecture 6 17

The Arguments are Evaluateddeclare Z=3fun {F X} {Browse X} 2 endY={F Z}{Browse Y}

X is evaluated as 3

3

2

declare Z=3

fun {F X}

{Browse X}

{Browse {X}} 2

end

Y={F fun {$} Z end}

{Browse Y}

X is evaluated as function value fun {$} Z end

<P/1>

3

2

04/18/23 COSC-3308-01, Lecture 6 18

Example Suppose we want to define the operator andthen (&& in Java) as a function, namely <expression1> andthen <expression2> is false if <expression1> is false, avoiding the evaluation of <expression2> (Exercise 2.8.6, page 109).

Attempt:fun {AndThen B1 B2}

if B1 then B2 else false end

end

if {AndThen X>0 Y>0} then … else …

04/18/23 COSC-3308-01, Lecture 6 19

Example

Does not work as wished because both X>0 and Y>0 are evaluated.

So, even if X>0 is false, Y should be bound in order to evaluate the expression Y>0!

fun {AndThen B1 B2}

if B1 then B2 else false end

end

if {AndThen X>0 Y>0} then … else …

04/18/23 COSC-3308-01, Lecture 6 20

Exampledeclarefun {AndThen B1 B2} if B1 then B2 else false endendX=~3Yif {AndThen X>0 Y>0} then {Browse 1}else {Browse 2}end Display nothing since Y is unbound! When called, all function’s arguments are evaluated.

04/18/23 COSC-3308-01, Lecture 6 21

Solution: Use Procedural Abstractions

fun {AndThen B1 B2}

if {B1} then {B2} else false end

end

if {AndThen fun{$} X>0 end fun{$} Y>0 end}

then … else … end

04/18/23 COSC-3308-01, Lecture 6 22

Example. Solutiondeclare

fun {AndThen BP1 BP2}

if {BP1} then {BP2} else false end

end

X=~3

Y

if {AndThen

fun{$} X>0 end

fun{$} Y>0 end}

then {Browse 1} else {Browse 2} end Display 2 (even if Y is unbound)

04/18/23 COSC-3308-01, Lecture 6 23

Genericity

To make a function generic is to let any specific entity (i.e., any operation or value) in the function body become an argument of the function.

The entity is abstracted out of the function body.

04/18/23 COSC-3308-01, Lecture 6 24

Genericity

Replace specific entities (zero 0 and addition +) by function arguments.

fun {SumList Ls}case Ls of nil then 0[] X|Lr then X+{SumList Lr}end

end

04/18/23 COSC-3308-01, Lecture 6 25

Genericityfun {SumList L}

case L of nil then 0[] X|L2 then X+{SumList L2}end

end

fun {FoldR L F U}case L of nil then U[] X|L2 then {F X {FoldR L2 F U}}end

end

04/18/23 COSC-3308-01, Lecture 6 26

Genericity SumList

fun {SumList Ls} {FoldR Ls fun {$ X Y} X+Y end 0 }end{Browse {SumList [1 2 3 4]}}

04/18/23 COSC-3308-01, Lecture 6 27

Genericity ProductList

fun {ProductList Ls} {FoldR Ls fun {$ X Y} X*Y end 1 }end{Browse {ProductList [1 2 3 4]}}

04/18/23 COSC-3308-01, Lecture 6 28

Genericity Some

fun {Some Ls} {FoldR Ls fun {$ X Y} X orelse Y end false } end{Browse {Some [false true false]}}

04/18/23 COSC-3308-01, Lecture 6 29

List Mapping

Mapping each element recursively calling function for each element Snoctruct list that takes output

Separate function calling by passing function as argument.

04/18/23 COSC-3308-01, Lecture 6 30

Other Generic Functions: Map

fun {Map Xs F} case Xs of nil then nil [] X|Xr then {F X}|{Map Xr F} endend{Browse {Map [1 2 3]

fun {$ X} X*X end}}

04/18/23 COSC-3308-01, Lecture 6 31

Other Generic Functions: Filterfun {Filter Xs P} case Xs of nil then nil [] X|Xr andthen {P X} then X|{Filter Xr P} [] X|Xr then {Filter Xr P} endend

{Browse {Filter [1 2 3] IsOdd}}

04/18/23 COSC-3308-01, Lecture 6 32

Instantiation Instantiation: the ability to return procedure

values as results from a procedure call. A factory of specialized functions.

declarefun {Add X}

fun {$ Y} X+Y endend

Inc = {Add 1}{Browse {Inc 5}} % shows 6

04/18/23 COSC-3308-01, Lecture 6 33

Explanations for Nesting Operator $ The previous Oz code can be rewritten as:

declare

fun {Add X}

Z = fun {$ Y} X+Y end

Z

end

Inc = {Add 1} % Inc is bound to value of Z

{Browse {Inc 5}} % shows 6

04/18/23 COSC-3308-01, Lecture 6 34

Embedding Embedding is when procedure values are put

in data structures. Embedding has many uses:

Modules: a module is a record that groups together a set of related operations (procedures).

Software components: a software component is a generic function that takes a set of modules as its arguments and returns a new module. It can be seen as specifying a module in terms of the modules it needs.

04/18/23 COSC-3308-01, Lecture 6 35

Embedding. Exampledeclare Algebralocal proc {Add X Y ?Z} Z=X+Y end proc {Mul X Y ?Z} Z=X*Y endin Algebra=op(add:Add mul:Mul) endA=2B=3{Browse {Algebra.add A B}}{Browse {Algebra.mul A B}}

Add and Mul are procedures embedded in a data structure.

04/18/23 COSC-3308-01, Lecture 6 36

Integer Loop Abstractions Integer loop: repeats an operation with a sequence

of integers:

proc {For I J P} if I > J then skip else {P I} {For I+1 J P} endend{For 1 10 Browse}

Linguistic abstraction for integer loops:for I in 1..10 do {Browse I} end

04/18/23 COSC-3308-01, Lecture 6 37

List Loop Abstractions List loop: repeats an operation for all elements of a list:

proc {ForAll Xs P} case Xs of nil then skip [] X|Xr then {P X} {ForAll Xr P} endend

{ForAll [a b c d] proc{$ I} {Browse I} end}

04/18/23 COSC-3308-01, Lecture 6 38

List Loop Abstractions

proc {ForAll Xs P} case Xs of nil then skip [] X|Xr then {P X} {ForAll Xr P} endend

Linguistic abstraction for list loops:

for I in [a b c d] do {Browse I}end

04/18/23 COSC-3308-01, Lecture 6 39

Other Examples

{Filter Xs F}returns all elements of Xs for which F returns true

{Some Xs F}tests whether Xs has an element for which F returns true

{All Xs F}tests whether F returns true for all elements of Xs

04/18/23 COSC-3308-01, Lecture 6 40

Folding Lists

Consider computing the sum of list elements …or the product …or all elements appended to a list …or the maximum …

What do they have in common?

Example: SumList

04/18/23 COSC-3308-01, Lecture 6 41

SumList: Naive

fun {SumList Xs}

case Xs

of nil then 0

[] X|Xr then {SumList Xr}+X

end

end

First step: make tail-recursive with accumulator.

04/18/23 COSC-3308-01, Lecture 6 42

SumList: Tail-Recursive

fun {SumList Xs N} case Xs of nil then N [] X|Xr then {SumList Xr N+X} endend{SumList Xs 0}

Question: what is about computing the sum? what is generic?

04/18/23 COSC-3308-01, Lecture 6 43

SumList: Tail-Recursive

fun {SumList Xs N} case Xs of nil then N [] X|Xr then {SumList Xr N+X} endend{SumList Xs 0}

Question: what is about computing the sum? what is generic?

04/18/23 COSC-3308-01, Lecture 6 44

How Does SumList Compute?

{SumList [2 5 7] 0} =

{SumList [5 7] 0+2} =

{SumList [7] (0+2)+5} =

{SumList nil ((0+2)+5)+7} = …

04/18/23 COSC-3308-01, Lecture 6 45

SumList Slightly Rewritten…

{SumList [2 5 7] 0} =

{SumList [5 7] {F 0 2}} =

{SumList [7] {F {F 0 2} 5}} =

{SumList nil {F {F {F 0 2} 5} 7} =

where F is

fun {F X Y} X+Y end

04/18/23 COSC-3308-01, Lecture 6 46

Left-Folding

Two values define “folding” initial value 0 for SumList binary function + for SumList

Left-folding {FoldL [x1 … xn] F S}

{F … {F {F S x1} x2} … xn}

or

(…((S F x1) F x2) … F xn)

04/18/23 COSC-3308-01, Lecture 6 47

Left-Folding

Two values define “folding” initial value 0 for SumList binary function + for SumList

Left-folding {FoldL [x1 … xn] F S}

{F … {F {F S x1} x2} … xn}

or

(…((S F x1) F x2) … F xn)

left is here!

04/18/23 COSC-3308-01, Lecture 6 48

FoldL

fun {FoldL Xs F S}

case Xs

of nil then S

[] X|Xr then {FoldL Xr F {F S X}}

end

end

04/18/23 COSC-3308-01, Lecture 6 49

SumList with FoldL

local

fun {Plus X Y} X+Y end

in

fun {SumList Xs}

{FoldL Xs Plus 0}

end

end

04/18/23 COSC-3308-01, Lecture 6 50

Properties of FoldL

Tail recursive First element of list is folded first…

what does that mean?

04/18/23 COSC-3308-01, Lecture 6 51

What Does This Do?

local

fun {Snoc Xr X}

X|Xr

end

in

fun {Foo Xs}

{FoldL Xs Snoc nil}

end

end

04/18/23 COSC-3308-01, Lecture 6 52

How Does Foo Compute?

{Foo [a b c]} =

{FoldL [a b c] Snoc nil} =

{FoldL [b c] Snoc {Snoc nil a}} =

{FoldL [b c] Snoc [a]} =

{FoldL [c] Snoc {Snoc [a] b}} =

{FoldL [c] Snoc [b a]} =

{FoldL nil Snoc {Snoc [b a] c}} =

{FoldL nil Snoc [c b a]} = [c b a]

04/18/23 COSC-3308-01, Lecture 6 53

Right-Folding

Two values define “folding” initial value binary function

Right-folding {FoldR [x1 … xn] F S}

{F x1 {F x2 … {F xn S} …}}

or

x1F(x2 F( … (xn F S) … ))

04/18/23 COSC-3308-01, Lecture 6 54

Right-Folding

Two values define “folding” initial value binary function

Right-folding {FoldR [x1 … xn] F S}

{F x1 {F x2 … {F xn S} …}}

or

x1F(x2 F( … (xn F S) … ))

right is here!

04/18/23 COSC-3308-01, Lecture 6 55

FoldR

fun {FoldR Xs F S}

case Xs

of nil then S

[] X|Xr then {F X {FoldR Xr F S}}

end

end

04/18/23 COSC-3308-01, Lecture 6 56

Properties of FoldR

Not tail-recursive Elements folded in order

04/18/23 COSC-3308-01, Lecture 6 57

FoldL or FoldR?

FoldL and FoldR compute the same value, if function F commutes:

{F X Y}=={F Y X}

If function commutes:FoldL FoldL tail-recursive

Otherwise: FoldL or FoldR depending on required order of result

04/18/23 COSC-3308-01, Lecture 6 58

Example: Appending Lists

Given: list of lists[[a b] [1 2] [e] [g]]

Task: compute all elements in one list in order

Solution:

fun {AppAll Xs}

{FoldR Xs Append nil}

end Question: What would happen with FoldL?

04/18/23 COSC-3308-01, Lecture 6 59

What would happen with FoldL?

fun {AppAllLeft Xs}

{FoldL Xs Append nil}

end

{AppAllLeft [[a b] [1 2] [e] [g]]} =

{FoldL [[a b] [1 2] [e] [g]] Append nil} =

{FoldL [[1 2] [e] [g]] Append {Append nil [a b]}}= ...

04/18/23 COSC-3308-01, Lecture 6 60

How Does AppAllLeft Compute?{FoldL [[1 2] [e] [g]] Append [a b]} =

{FoldL [[e] [g]] Append {Append [a b] [1 2]}} =

{FoldL [[e] [g]] Append [a b 1 2]} =

{FoldL [[g]] Append {Append [a b 1 2] [e]}} =

{FoldL [[g]] Append [a b 1 2 e]} =

{FoldL nil Append {Append [a b 1 2 e] [g]}} =

{FoldL nil Append [a b 1 2 e g]} =

= [a b 1 2 e g]

04/18/23 COSC-3308-01, Lecture 6 61

Summary so far Many operations can be partitioned into

pattern implementing recursion application of operations

operations to be applied

Typical patterns Map mapping elements FoldL/FoldR folding elements Filter filtering elements Sort sorting elements …

04/18/23 COSC-3308-01, Lecture 6 62

Abstract Data Types

Overview

04/18/23 COSC-3308-01, Lecture 6 63

Data Types

Data type set of values operations on these values

Primitive data types records numbers …

Abstract data types completely defined by its operations (interface) implementation can be changed without changing use

04/18/23 COSC-3308-01, Lecture 6 64

Motivation

Sufficient to understand interface only.

Software components can be developed independently, as long as only the interface is used.

Developers need not to know implementation details.

04/18/23 COSC-3308-01, Lecture 6 65

Outlook

How to define abstract data types

How to organize abstract data types

How to use abstract data types

04/18/23 COSC-3308-01, Lecture 6 66

Abstract data types (ADTs) A type is abstract if it is completely defined by

its set of operations, regardless of the implementation.

ADTs: it is possible to change the implementation of an ADT without changing its use.

The ADT is described by a set of procedures Including how to create a value of the ADT.

These operations are the only thing that a user of the abstraction can assume.

04/18/23 COSC-3308-01, Lecture 6 67

Example: stack

Assume we want to define a new data type stack T whose elements are of any type T.

We define the following operations (with type definitions):

fun {NewStack}: stack Tfun {Push stack T T }: stack Tproc {Pop stack T ?T ?stack T}fun {IsEmpty stack T}: Bool

04/18/23 COSC-3308-01, Lecture 6 68

Example: stack (algebraic properties)

Algebraic properties are logical relations between ADT’s operations.

These operations normally satisfy certain laws (properties):

{IsEmpty {NewStack}} = true For any stack S, {IsEmpty {Push S}} = false For any E and S, {Pop {Push S E} E S} holds. For any stack S, {Pop {NewStack} S} raises error.

04/18/23 COSC-3308-01, Lecture 6 69

stack (implementation I) using listsfun {NewStack} nil end

fun {Push S E} E|S end

proc {Pop E|S ?E1 ?S1}

E1 = E

S1 = S

end

fun {IsEmpty S} S==nil end

04/18/23 COSC-3308-01, Lecture 6 70

stack (implementation II) using tuplesfun {NewStack} emptyStack end

fun {Push S E} stack(E S) end

proc {Pop stack(E S) E1 S1} E1 = E

S1 = S

end

fun {IsEmpty S} S==emptyStack end

04/18/23 COSC-3308-01, Lecture 6 71

Why the Stack is Abstract?

A program that uses the stack will work with either implementation (gives the same result).

declare Top S4

% ... either implementation

S1={NewStack}

S2={Push S1 2}

S3={Push S2 5}

{Pop S3 Top S4}

{Browse Top} 5

04/18/23 COSC-3308-01, Lecture 6 72

What is a Dictionary?

A dictionary is a finite mapping from a set of simple constants to a set of language entities.

Each constant maps to one language entity. The constants are called keys because they

unlock the path to the entity, in some intuitive sense.

We will use atoms or integers as constants. Goal: create the mapping dynamically, i.e.,

by adding new keys during the execution.

04/18/23 COSC-3308-01, Lecture 6 73

Example: Dictionaries Designing the interface{MakeDict}

returns new dictionary{DictMember D F}

tests whether feature F is member of dictionary D{DictAccess D F}

returns the value of feature F in D{DictAdjoin D F X}

returns the dictionary with value X at feature F adjoined

Interface depends on purpose, could be richer.

04/18/23 COSC-3308-01, Lecture 6 74

Using the Dict ADT

Now we can write programs using the ADT without even having an implementation for it.

Implementation can be provided later. Eases software development in large teams.

04/18/23 COSC-3308-01, Lecture 6 75

Implementing the Dict ADT

Now we can decide on a possible implementation for the Dict ADT: based on pairlists, based on records.

Regardless on what we decide, programs using the ADT will work! the interface is a contract between use and

implementation.

04/18/23 COSC-3308-01, Lecture 6 76

Dict: Pairlistsfun {MakeDict} nilendfun {DictMember D F} case D of nil then false [] G#X|Dr then if G==F then true else {DictMember Dr F} end endend Example: telephone book[name1#62565243 name2#67893421 taxi1#65221111...]

04/18/23 COSC-3308-01, Lecture 6 77

Dict: Recordsfun {MakeDict} mr %start making the recordendfun {DictMember D F} {HasFeature D F}endfun {DictAccess D F} D.Fendfun {DictAdjoin D F X} {AdjoinAt D F X}end Example: telephone bookd(name1:62565243 name2:67893421 taxi1:65521111...)

04/18/23 COSC-3308-01, Lecture 6 78

HasFeature and AdjoinAtdeclareX=p(n:'Joe' age:26)Y={Value.'.' X n}{Browse Y} Z={Value.hasFeature X age}{Browse Z} U={HasFeature X age}{Browse U} V={AdjoinAt X s 'm'}{Browse V} T={AdjoinAt V age 27}{Browse T}

'Joe'

true

true

p(age:26 n:'Joe' s:'m')

p(age:27 n:'Joe' s:'m')

04/18/23 COSC-3308-01, Lecture 6 79

Evolution of ADTs Important aspect of developing ADTs

start with simple (possibly inefficient) implementation;

refine to better (more efficient) implementation; refine to carefully chosen implementation:

hash table search tree

All of evolution is local to ADT: no change of programs using ADT is needed!

04/18/23 COSC-3308-01, Lecture 6 80

Summary

Higher-Order Programming Abstract Data Types

04/18/23 COSC-3308-01, Lecture 6 81

Reading suggestions

From [van Roy,Haridi; 2004] Chapter 3, Sections 3.2-3.9 Exercises 2.9.8, 3.10.6-3.10.17

04/18/23 COSC-3308-01, Lecture 6 82

Coming up next

Declarative concurrency, and Demand-driven execution Chapter 3, Sections 3.4-3.8 Chapter 4, Sections 4.1-4.5

04/18/23 COSC-3308-01, Lecture 6 83

Thank you for your attention!

Questions?