<<

CS 242 Language Sequence

The Algol Family and ML Lisp Algol 60

Algol 68

John Mitchell Pascal

ML Modula

Many other languages: Reading: Chapter 5 Algol 58, Algol W, Euclid, EL1, Mesa (PARC), … Modula-2, Oberon, Modula-3 (DEC)

Algol 60 Algol 60 Sample

‹Basic Language of 1960 real procedure average(A,n); • Simple imperative language + functions real array A; integer n; no array bounds • Successful syntax, BNF -- used by many successors begin – statement oriented – Begin … End blocks (like { … } ) real sum; sum := 0; – if … then … else for i = 1 step 1 until n do • Recursive functions and stack storage allocation sum := sum + A[i]; • Fewer ad hoc restrictions than Fortran average := sum/n no ; here – General array references: A[ x + [3]*y] end; • Type discipline was improved by later languages

• Very influential but not widely used in US set procedure return value by assignment

Algol oddity Some trouble spots in Algol 60

‹Question ‹Type discipline improved by later languages • Is x := x equivalent to doing nothing? • parameter types can be array ‹Interesting answer in Algol – no array bounds integer procedure p; • parameter type can be procedure – no argument or return types for procedure parameter begin …. ‹Parameter passing methods p := p • Pass-by-name had various anomalies – “Copy rule” based on substitution, interacts with side effects …. • Pass-by-value expensive for arrays end; • Assignment here is actually a recursive call ‹Some awkward control issues • goto out of requires memory management

1 Algol 60 Pass-by-name Algol 68

‹Substitute text of actual parameter ‹Considered difficult to understand • Unpredictable with side effects! • Idiosyncratic terminology ‹Example – types were called “modes” – arrays were called “multiple values” procedure inc2(i, j); • vW grammars instead of BNF integer i, j; – context-sensitive grammar invented by A. van Wijngaarden begin begin • Elaborate i := i+1; k := k+1; • Complicated type conversions j := j+1 A[k] := A[k] +1 ‹Fixed some problems of Algol 60 end; end; • Eliminated pass-by-name inc2 (k, A[k]); Is this what you expected? ‹Not widely adopted

Algol 68 Modes Other features of Algol 68

‹Primitive modes ‹Compound modes ‹Storage management • int • arrays • Local storage on stack • real • structures • Heap storage, explicit alloc and garbage collection • char • procedures ‹Parameter passing • bool • sets • Pass-by-value • string • pointers • Use pointer types to obtain Pass-by-reference • compl (complex) ‹Assignable procedure variables • bits Rich and structured • Follow “orthogonality” principle rigorously • bytes type system is a • sema () major contribution of • format (I/O) Algol 68 Source: Tanenbaum, Computing Surveys • file

Pascal Limitations of Pascal

‹Revised type system of Algol ‹Array bounds part of type illegal • Good data-structuring concepts procedure p(a : array [1..10] of integer) – records, variants, subranges procedure p(n: integer, a : array [1..n] of integer) • More restrictive than Algol 60/68 – Procedure parameters cannot have procedure parameters • Attempt at orthogonal design backfires – parameter must be given a type ‹Popular teaching language – type cannot contain variables ‹Simple one-pass How could this have happened? Emphasis on teaching ‹Not successful for “industrial-strength” projects • Kernighan -- Why Pascal is not my favorite language • Left niche for C; niche has expanded!!

2 C ML

‹Typed programming language Designed by Dennis Ritchie for writing Unix ‹Intended for interactive use ‹Evolved from B, which was based on BCPL • B was an untyped language; C adds some checking ‹Combination of Lisp and Algol-like features ‹Relation between arrays and pointers • Expression-oriented • Higher-order functions • An array is treated as a pointer to first element • Garbage collection • E1[E2] is equivalent to ptr dereference *((E1)+(E2)) • Abstract data types • Pointer arithmetic is not common in other languages • Module system ‹Ritchie quote • Exceptions • “C is quirky, flawed, and a tremendous success.” ‹General purpose non-C-like, not OO language • Related languages: Haskell, OCAML, …

Why study ML ? Recent implementation

• Types and type checking – General issues in static/dynamic typing –Type inference – Polymorphism and Generic Programming • Memory management – Static and block structure – Function activation records, higher-order functions • Control – Force and delay –Exceptions – Tail recursion and continuations

History of ML Logic for Computable Functions

‹Robin Milner ‹Dana Scott, 1969 ‹Logic for Computable • Formulate logic for proving properties of typed Functions functional programs • Stanford 1970-71 ‹Milner • Edinburgh 1972-1995 • Project to automate logic ‹Meta-Language of the • Notation for programs LCF system • Notation for assertions and proofs • Theorem proving • Need to write programs that find proofs – Too much work to construct full formal proof by hand • Type system • Make sure proofs are correct • Higher-order functions

3 LCF proof search Tactics in ML type system

‹Tactic: function that tries to find proof ‹Tactic has a functional type tactic : formula → proof succeed and return proof ‹Type system must allow “failure” tactic(formula) = search forever fail succeed and return proof tactic(formula) = search forever fail and raise exception ‹Express tactics in the Meta-Language (ML) ‹Use type system to facilitate correctness

Function types in ML Higher-Order Functions f : A → B means ‹Tactic is a function for every x ∈ A, ‹Method for combining tactics is a function on some element y=f(x) ∈ B functions f(x) = run forever ‹Example: terminate by raising an exception f(tactic1, tactic2) =

λ formula. try tactic1(formula) In words, “if f(x) terminates normally, then f(x)∈ B.” else tactic2 (formula) Addition never occurs in f(x)+3 if f(x) raises exception.

This form of function type arises directly from motivating application for ML. Integration of type system and exception mechanism mentioned in Milner’s 1991 .

Basic Overview of ML Overview by Type

‹Interactive compiler: read-eval-print ‹Booleans • Compiler infers type before compiling or executing • true, false : bool Type system does not allow casts or other loopholes. • if … then … else … (types must match) ‹Examples ‹Integers - (5+3)-2; • 0, 1, 2, … : int > val it = 6 : int • +, * , … : int * int → int and so on … - if 5>3 then “Bob” else “Fido”; ‹Strings > val it = “Bob” : string • “Austin Powers” -5=4; ‹Reals > val it = false : bool • 1.0, 2.2, 3.14159, … decimal point used to disambiguate

4 Compound Types Patterns and Declarations

‹Tuples ‹Patterns can be used in place of variables ::= | | | … • (4, 5, “noxious”) : int * int * string ‹Value declarations ‹Lists • General form • nil val = • 1 :: [2, 3, 4] infix cons notation • Examples ‹Records val myTuple = (“Conrad”, “Lorenz”); • {name = “Fido”, hungry=true} val (x,y) = myTuple; : {name : string, hungry : bool} val myList = [1, 2, 3, 4]; val x::rest = myList; • Local declarations let val x = 2+3 in x*4 end;

Functions and Pattern Matching Map function on lists

‹Anonymous function ‹Apply function to every element of list • fn x => x+1; like Lisp lambda fun map (f, nil) = nil ‹Declaration form | map (f, x::xs) = f(x) :: map (f,xs);

• fun = map (fn x => x+1, [1,2,3]); [2,3,4]

| = … ‹Compare to Lisp | = … ‹Examples (define map (lambda (f xs) • fun f (x,y) = x+y; actual par must match pattern (x,y) (if (eq? xs ()) () • fun length nil = 0 (cons (f (car xs)) (map f (cdr xs))) | length (x::s) = 1 + length(s); )))

More functions on lists More efficient reverse function

‹Reverse a list fun reverse xs = fun reverse nil = nil let fun rev ( nil, z ) = z | reverse (x::xs) = append ((reverse xs), [x]); | rev( y::ys, z ) = rev( ys, y::z ) ‹Append lists in rev( xs, nil ) fun append(nil, ys) = ys end; | append(x::xs, ys) = x :: append(xs, ys); ‹Questions • How efficient is reverse? 1 3 • Can you do this with only one pass through list? 2 2 2 2 3 3 1 3 1 1

5 Datatype Declarations Datatype and pattern matching

‹General form ‹Recursively defined data structure datatype = | … | datatype tree = leaf of int | node of int*tree*tree ::= | of ‹Examples node(4, node(3,leaf(1), leaf(2)), 4 node(5,leaf(6), leaf(7)) • datatype color = red | yellow | blue 3 5 ) – elements are red, yellow, blue • datatype atom = atm of string | nmbr of int 1 2 6 7 – elements are atm(“A”), atm(“B”), …, nmbr(0), nmbr(1), ... ‹Recursive function • datatype list = nil | cons of atom*list fun sum (leaf n) = n – elements are nil, cons(atm(“A”), nil), … | sum (node(n,t1,t2)) = n + sum(t1) + sum(t2) cons(nmbr(2), cons(atm(“ugh”), nil)), ...

Example: Evaluating Expressions Case expression

‹Define datatype of expressions ‹Datatype datatype exp = Var of int | Const of int | Plus of exp*exp; datatype exp = Var of int | Const of int | Plus of exp*exp; Write (x+3)+y as Plus(Plus(Var(1),Const(3)), Var(2)) ‹Case expression ‹Evaluation function case e of fun ev(Var(n)) = Var(n) Var(n) => … | | ev(Const(n)) = Const(n) Const(n) => …. | | ev(Plus(e1,e2)) = … Plus(e1,e2) => … Examples ev(Plus(Const(3),Const(2))) Const(5) ev(Plus(Var(1),Plus(Const(2),Const(3)))) ev(Plus(Var(1), Const(5))

Evaluation by cases Core ML datatype exp = Var of int | Const of int | Plus of exp*exp; ‹Basic Types ‹Patterns fun ev(Var(n)) = Var(n) • Unit ‹Declarations • Booleans | ev(Const(n)) = Const(n) ‹Functions • Integers | ev(Plus(e1,e2)) = (case ev(e1) of ‹Polymorphism • Strings Var(n) => Plus(Var(n),ev(e2)) | • Reals ‹Overloading Const(n) => (case ev(e2) of • Tuples ‹Type declarations Var(m) => Plus(Const(n),Var(m)) | • Lists ‹Exceptions Const(m) => Const(n+m) | • Records ‹Reference Cells Plus(e3,e4) => Plus(Const(n),Plus(e3,e4)) ) | Plus(e3,e4) => Plus(Plus(e3,e4),ev(e2)) );

6 Variables and assignment ML imperative constructs

‹General terminology: L-values and R-values ‹ML reference cells • Assignment y := x+3 • Different types for location and contents – Identifier on left refers to a memory location, called L-value x : int non-assignable integer value – Identifier on right refers to contents, called R-value y : int ref location whose contents must be integer ‹Variables !y the contents of location y • Most languages ref x expression creating new cell initialized to x – A variable names a storage location • ML assignment – Contents of location can be read, can be changed operator := applied to memory cell and new contents • ML reference cell • Examples – A mutable cell is another type of value y := x+3 place value of x+3 in cell y; requires x:int – Explicit operations to read contents or change contents y := !y + 3 add 3 to contents of y and store in location y – Separates naming (declaration of identifiers) from “variables”

ML examples Core ML

‹Create cell and change contents ‹Basic Types ‹Patterns val x = ref “Bob”; x • Unit BobBill ‹Declarations x := “Bill”; • Booleans ‹Functions • Integers ‹Create cell and increment y ‹Polymorphism val y = ref 0; 10 • Strings ‹Overloading y := !y + 1; • Reals ‹Type declarations ‹While loop • Tuples val i = ref 0; • Lists ‹Exceptions while !i < 10 do i := !i +1; • Records ‹Reference Cells !i;

7