510 likes | 717 Views
Christian Schulte cschulte@kth.se Software and Computer Systems School of Information and Communication Technology KTH – Royal Institute of Technology Stockholm, Sweden. Functional Programming in Erlang. ID1218 Lecture 02 2009-10-28. Reminder & Overview. Functional Programming.
E N D
Christian Schulte cschulte@kth.se Software and Computer Systems School of Information and Communication Technology KTH – Royal Institute of Technology Stockholm, Sweden Functional Programming in Erlang ID1218 Lecture 02 2009-10-28
Reminder & Overview ID1218, Christian Schulte
Functional Programming • Compute by evaluating functions returning results • Techniques • recursion with last-call-optimization • pattern matching • list processing • higher-order programming • accumulators ID1218, Christian Schulte
Functional Programming in Erlang • Data types: values • primitive: integers, floats, atoms • compound: tuples, lists • Programs consist of functions • identified by atom and arity • defined by several clauses • arguments are passed by value • clauses are evaluated • evaluation returns value ID1218, Christian Schulte
Function Definition • Function defined by several clauses • clauses separated by ; • last clause terminated by . • variable scope is per clause (anonymous variable _) • Clause consists of head and body • separated by -> • head can contain guard after when • clauses tried in textual order until matching clause is found (pattern matches and guard is true) • Guards: tests, comparisons, conjunction, disjunction ID1218, Christian Schulte
Program Organization • Programs consists of several modules • Module • are named • export functions • import other modules • Function calls • either locally defined or imported functions • or functions qualified by module name ID1218, Christian Schulte
Overview • Introduction to Erlang • second look: lists and tuples, pattern matching • third look: what do we need to understand • How do Erlang programs compute • make programs simple • how exactly does computation proceed • Next lecture • accumulators • higher-order programming ID1218, Christian Schulte
A Second Look ID1218, Christian Schulte
Tuples • Combine several values • here: 1, a, 2 • position is significant! {} {1,a,2} 1 a 2 ID1218, Christian Schulte
Lists • A list contains a sequence of elements • A list • is the empty list [], or • consists of a cons (or list pair) with head and tail • head contains an element • tail contains a list ID1218, Christian Schulte
[|] [|] [|] a b c [] | | An Example List • After evaluation of [a|[b|[c|[]]]] • Can also be written as [a,b,c] [a|[b,c]] [a,b|[c|[]]] ID1218, Christian Schulte
Head And Tail • The head and tail can be accessed by builtin functions (BIFs) hd/1 and tl/1 hd([X|Xr]) evaluates to X tl([X|Xr]) evaluates to Xr ID1218, Christian Schulte
Example of Head and Tail • hd([a,b,c]) evaluates to a • tl([a,b,c]) evaluates to [b,c] • hd(tl(tl([a,b,c]))) evaluates to c • Draw the trees! ID1218, Christian Schulte
How to Process Lists • Given: list of integers • Wanted: sum of its elements • implement function sum • Inductive definition over list structure • Sum of empty list is 0 • Sum of non-empty list Xs is hd(Xs) + sum(tl(Xs)) ID1218, Christian Schulte
Sum of a List sum(Xs) when Xs==[] -> 0; sum(Xs) -> hd(Xs)+sum(tl(Xs)). ID1218, Christian Schulte
General Method • Lists are processed recursively • base case: list is empty ([]) • inductive case: list is cons access head, access tail • Powerful and convenient technique • pattern matching • matches patterns of values and provides access to fields of compound data structures ID1218, Christian Schulte
Sum with Pattern Matching sum([]) -> 0; sum([X|Xr]) -> X+sum(Xr). ID1218, Christian Schulte
Pattern Matching • A pattern is constructed like a value but also allows variables in the pattern • A pattern matches a value, if • the types agree (tuple matches tuple, list matches list, …) • for tuples, the arity (number of fields must agree) • the values agree • When a pattern matches, the variables are assigned to the matched values ID1218, Christian Schulte
Pattern Matching • Can be used with the assignment operator = • For example {[X|Xr],4,{A,B}} = {[1],4,{b,a}} matches with X=1, Xr=[], A=b, B=a • But [] does not match [_|_], … ID1218, Christian Schulte
Single Assignment Variables • A variable can be assigned only to the same value X=[1,2],X=[1,2] • otherwise runtime error • Major difference to Java, C, C++, … • variables change over time • also: stateful variables and programs • Single assignment variables simplify • reasoning over programs • concurrent programming ID1218, Christian Schulte
Length of a List • Inductive definition • length of empty list is 0 • length of cons is 1 + length of tail len([]) -> 0; len([_|Xr]) -> 1+len(Xr). ID1218, Christian Schulte
Case Expression len(Xs) -> case Xs of [] -> 0; [_|Xr] -> 1+len(Xr) end. • Like new function defined with several clauses • Functions with a single clause are sufficient • Scope rule: • if variable X introduced in clause and used after end • X must be introduced in all clauses ID1218, Christian Schulte
If Expression fac(N) -> if N==0 -> 1; N>0 -> N*fac(N-1) end. • Scoping as with case ID1218, Christian Schulte
Look Two: Summary • List is either empty or cons with head and tail • List processing is recursive processing • Useful for this is pattern matching • Clauses can be replaced by case expression ID1218, Christian Schulte
A Third Look ID1218, Christian Schulte
A Better Length? len(Xs) -> len(Xs,0). len([],N) -> N; len([_|Xr],N) -> len(Xr,N+1). • Two different functions: len/1 and len/2 • Better, because • much faster (but it has one more argument?) • uses less memory (what memory? heap? stack?) ID1218, Christian Schulte
Appending Two Lists app([],Ys) -> Ys; app([X|Xr],Ys) -> [X|app(Xr,Ys)]. • How much memory needed? • Stack space… in the length of the first list… Why? ID1218, Christian Schulte
Reversing a List rev([]) -> []; rev([X|Xr]) -> app(rev(Xr),[X]). • How much time needed? • grows quadratic with the length of the input list… • why? how can one find out? ID1218, Christian Schulte
Reversing a List: Better rev(Xs) -> rev(Xs,[]). rev([],Ys) -> Ys; rev([X|Xr],Ys) -> rev(Xr,[X|Ys]). • How much time needed? • grows only linear with the length of the input list… • how does this work? • can we do that mechanically? The same as len/2… ID1218, Christian Schulte
How Programs Compute The MiniErlang Machine ID1218, Christian Schulte
Erlang Semantics • Semantics will define • how programs compute • operational semantics • abstract machine (implementation blueprint) • Strategy • define semantics for very simple Erlang programs • captures the essence of how programs compute • explains in particular how much stack space is needed ID1218, Christian Schulte
The MiniErlang Machine • Executes MiniErlang programs • Uses two stacks • expression stack: what needs to be evaluated • value stack: was has already been evaluated • Starts with a single expression to be evaluated • the value stack is empty • Finishes with a single value (the result) • all expressions have been evaluated • Executes expressions and instructions • instructions perform operations after all required arguments have been evaluated ID1218, Christian Schulte
Roadmap: MiniErlang • What to compute with • MiniErlang expressions and programs • What are the results • MiniErlang Values • What are the instructions • for compound value construction and function call • How are functions called • parameters are passed by substitution • considers only matching clauses • clauses have patterns (we ignore guards) ID1218, Christian Schulte
Evaluating Values ID1218, Christian Schulte
MiniErlang Values • A MiniErlang value is an integer or a list • other values are similar • In short notation V := int | [] | [V1|V2] • known as BNF notation: discussed later • so: values are referred to by V (possibly subscripted) • can be: any integer, the empty list, a cons consisting of two values V1 and V2 ID1218, Christian Schulte
MiniErlang Expressions • A MiniErlang expression is a value, a variable, or a function call E := int | [] | [E1|E2] | X | F(E1,…, En) • expressions referred to by E • variables referred to by X • function names referred to by F ID1218, Christian Schulte
MiniErlang Machine • MiniErlang machine Es ; Vs→ Es’ ; Vs’ transforms a pair (separated by ;) of • expression stack Es and value stack Vs into a new pair of • expression stack Es’ and value stack Vs’ • Initial configuration: • expression we want to evaluate on expression stack • Final configuration: • single value as result on value stack ID1218, Christian Schulte
Stacks • We write stacks as X1 … Xn Xr • top of stack X1 • n-th element Xn • more elements Xr • empty stack • Pushing X to stack Xr: X Xr • Popping X from stack X Xr: Xr ID1218, Christian Schulte
MiniErlang Execution Idea • Simple case: an integer evaluates to itself • the result of an integer expression… …is an integer value • MiniErlang machine i Er ; Vs→ Er ; i Vs • if the expression stack has the integer i as top of stack… • execution yields: the expression i is popped from the expression stack and pushed on to the value stack • same for empty list ID1218, Christian Schulte
MiniErlang Instruction Idea • How to evaluate a list expression [E1|E2] • first evaluate E1 , to a value V1, … • then evaluate E2 , to a value V2, … • then construct a new value [V1|V2] • Use an instruction that says: build a list • makes the assumption that values needed are on the value stack • execution will pop two values, push a new list value • when [E1|E2] is executed, E1 andE2 and the instruction CONS are pushed on the expression stack ID1218, Christian Schulte
Evaluating a List Expression • Evaluate a list expression [E1|E2]Er ; Vs → E1E2CONSEr ; Vs • Execute a CONS instruction CONSEr ; V1V2Vs → Er ; [V2|V1]Vs ID1218, Christian Schulte
Example • We want to evaluate the expression [1|[]] (that is, just the list [1]) • Start configuration of our machine [1|[]] ; • expression stack: [1|[]] • empty value stack: • What should be the end configuration: ; [1|[]] • empty expression stack: • result on value stack: [1|[]] ID1218, Christian Schulte
Let’s Do It! [1|[]] ; → … [E1|E2]Er ; Vs → E1E2CONSEr ; Vs ID1218, Christian Schulte
Let’s Do It! [1|[]] ; → 1 []CONS ; → … i Er ; Vs→ Er ; iVs ID1218, Christian Schulte
Let’s Do It! [1|[]] ; → 1 []CONS ; → []CONS ;1 → … i Er ; Vs→ Er ; iVs ID1218, Christian Schulte
Let’s Do It! [1|[]] ; → 1 []CONS ; → []CONS ;1 → CONS ;[]1 → … CONSEr ; V1V2Vs → Er ; [V2|V1]Vs ID1218, Christian Schulte
Let’s Do It! [1|[]] ; → 1 []CONS ; → []CONS ;1 → CONS ;[]1 → ;[1|[]] ID1218, Christian Schulte
Summary • MiniErlang • values • expressions • MiniErlang machine • operates on expression and value stack • evaluates topmost expression on expr stack • executes topmost instruction on expr stack • Start state: single expr on expr stack • Final state: single value on value stack ID1218, Christian Schulte
Summary & Homework ID1218, Christian Schulte
Summary: MiniErlang • Stack-based operational semantics • expressions, values, patterns, substitutions, matching • What did we learn • how to describe how programs compute • semi-gentle introduction to semantics • better understanding of Erlang programs • blueprint of a stack-based implementation • What will we use it for • tool for analyzing how Erlang programs compute ID1218, Christian Schulte