Functional Programming Variables in Imperative Languages Variables In
Total Page:16
File Type:pdf, Size:1020Kb
Variables in Imperative Languages • A variable in an imperative programming language can be Functional Programming regarded as an abstraction of what? Another representative from the Declarative paradigm • Assignment is ? 1 2 Variables in Imperative Languages Sequences of Instructions Von Neumann architecture drives the imperative paradigm: • Imperative programs are sequences of instructions because to • Store: individually addressable locations. be executed they must be stored in memory in a sequence of locations, and because of the way the standard fetch/execute cycle works. • Machine language: sequences of instructions changing the contents of store locations (referred to by their addresses). • The control of such execution, involving loops of different kinds, is a common source of bugs in imperative programs. • High-level imperative languages: sequences of instructions changing the values of variables (referred to by their names). • This influences the whole paradigm. In particular: 1. Issues around assignment. 2. Control of execution of sequences of instructions. 3 4 Assignment Referential Transparency • Referential transparency means • There are problems with assignment and the management of – The meaning (or the effect, or the value) of an expression is the store. These relate to the same wherever (and whenever) it occurs. • Imperative languages do not support referential transparency. • Side-effects • Trivial example: • Aliasing X := 0; • Referential transparency Write(X); X := X + 1; Write(X); • This problem becomes even worse when parallel execution is considered. Why? 5 6 Summary The Functional Approach • Here are two examples of function definitions (syntax may change!): • Imperative languages are based on standard computer architecture. fun double (n) = n+n; • The advantage of this is run-time efficiency. fun square (n) = n*n; • A (pure) functional program is simply a collection of function definitions. • BUT… • A functional programming system allows us to store such function definitions, and then ask for specific expressions to be evaluated. 1. It facilitates errors. • Examples: 2. It makes bug-tracing difficult. 3. It makes programs hard to read and understand. # double 7; # double( square 2 ) 4. (Backus, 1978) It limits the programmer's thinking and 14 8 inhibits the problem-solving process. # map square [1, 2, 3]; 7 [1, 4, 9] 8 A word on the ML language (and syntax) Functional Programming We will be using ML, a general-purpose functional programming language developed by Robin Milner et al. in the 1970s at the University of Edinburgh. • Note that a functional language is inherently declarative. http://en.wikipedia.org/wiki/ML(programming_language) http://sml-family.org/ • Such function definitions are simply statements of what our … functions are. There are many dialects and (industry adopted) languages spawn from ML! We will use a freely available, web-based, simple (Oca)ML interpreter, and from now on we will adopt its syntax: • Main operation is the application of functions to data (or other functions!), different from imperative languages, whose main http://try.ocamlpro.com/ function is manipulating the state/store, i.e. assignment. The general syntax of ML is slightly different, e.g. • There is an analogy with Prolog. But remember that in Prolog fun double (n) = n+n; is let square n = n*n we dealt with predicates, not functions, and we achieve goals or let rec factorial n = … for recursive functions rather than evaluate expressions. Refer to the tutorials/docs on the web site! 9 10 (also http://caml.inria.fr/pub/docs/manual-ocaml/ ) The Functional Approach The Functional Approach • A program consists of a collection of function definitions, and a `run' amounts to an evaluation of an expression involving these functions • Programs in functional languages are generally shorter, easier to over input data. understand, design, debug, and maintain, than imperative counterpart. • Function are first class objects (higher order functions), e.g. map. • The intention is to focus on the computations which are to be done, not on how to fit them to the structure of the machine. • Typically recursion is used in functional programming languages, iteration is used in imperative languages. • Assignment is not a part of this paradigm, nor is the idea of a sequence of instructions. • Modern functional languages are • Under this paradigm: – are strongly typed (most type errors detected statically by the compiler, no type errors at runtime) – provide type inference. 1. Side-effects can be completely avoided. 2. Aliasing is not possible. • (Pure) functional programs are stateless – (good news?) 3. Referential transparency can be supported. 11 12 FP in the Real World List of functional programming languages from homepages.inf.ed.ac.uk/wadler/realworld/ : • Industrial – Erlang, an e-commerce database, Partial evaluator for airline • Many functional languages, … scheduling, Combinators for financial derivatives • … and imperative ones that support forms of functional usage. • Compilers, Interpreters and Partial Evaluators, Syntax and Analysis Tools • Theorem Provers and Reasoning Assistants • http://en.wikipedia.org/wiki/ • Network Toolkits and Applications, Web, HTML, XML, XSLT List_of_programming_languages_by_type#Functional_languages • Natural Language Processing and Speech Recognition (pure and impure) • Numerically Based Applications, Computer Algebra – MC-SYM - computes 3D shape of nucleic acid, FFTW - Fastest Fourier Transform in the West, BlurFit - model focal plane imaging • Pure: Charity Clean Curry Haskell Hope Miranda Idris • Database Systems • Impure: C# Erlang F#, Java (since version 8) Lisp Clojure Scheme • Operating Systems Mathematica ML OCaml R Scala Python • Light and sound • There are more impure languages! – Lula: a system for theather lighting, Scheme Score 14 1. Programs 2. Data Structures • A program consists of a collection of function definitions: • Lists are the main basic data structure. • Careful with types! inOcaML + is int * int -> int +. is float * float -> float • Notations (ML): let double(n) = n +. n [2;6;4;5] is a list let square(n) = n *. n [ ] is an empty list let avg(x,y) = (x +. y) /. 2.0 List.hd [2;6;4;5] is 2 (an integer) let sqAvg(x,y) = avg(square(x),square(y)) List.tl [2;6;4;5] is [6;4;5] (a list) • The the following can be evaluated: h :: t 2 :: [6;4;5] is … square( double(6.0) ) • Example function involving lists (more later): sqAvg( 5.0 , 7.0 ) let rec length l = match l with • In each case the system would respond with the value, respectively | [ ] -> 0 144 and 37. | _ -> 1 + length( List.tl l) 15 16 3. Program Control 4. Pattern-Matching • Two equivalent definitions: • We have composition of functions: – apply one function to some value(s), and then apply another let isEmpty( l ) = if l = [ ] then true else false function to the result. (Like SqAvg above). let isEmpty( l ) = match l with • There is no notion of program loop, so recursion is essential | [ ] -> true (see the Length function above). | h :: t -> false • Functional programming also has an `if' construct, to distinguish • When we ask to evaluate (say) isEmpty([4,1,7]), a matching cases. process takes place, and as a result the second line of the definition is used. • Example: • (See also the length function above.) let max (x, y) = if x >= y then x else y; let isEmpty ( l ) = if l = [ ] then true else false; 17 18 More Pattern Matching Further Pattern Matching Examples let rec isM x l = if l = [ ] then false let rec addUpTo n = match n with | 0 -> 0 | n when n>0 -> n + addUpTo (n -1);; else if x = List.hd( l ) then true else isMember x (List.tl l) let rec factorial n = match n with | 0 -> 1 | _ -> n * factorial (n - 1);; is equivalent to let rec listAsFarAs x l = match l with | [ ] -> [ ] | h :: t when h = x -> [x] let rec isM m l = match l with | h :: t -> h :: listAsFarAs x t;; | [ ] -> false | n :: t when n = m -> true let rec doubleList l = match l with | [ ] -> [ ] | n :: t when n <> m -> isM m t | h :: t -> double(h) :: doubleList t;; let rec sumList l = match l with | [x] -> x | h :: t -> h +. sumList t ;; The word pattern here refers to the formal structure of an expression ([ ] and h :: t are patterns). Pattern-matching is an essential part of functional let listAvg l = sumList l /. (float_of_int) (length l) ;; languages. (As it is also with Prolog*.) *actually: unification 19 20 5. Evaluation 6. Higher-order Functions • A functional programming system simply allows evaluation of expressions. An actual evaluation is done by a process called reduction or rewriting. • In functional languages there is the possibility to define functions Here is how it works. which have functions as parameters, or which return functions as results. This is what is meant by higher-order functions. • Say we wish to evaluate listAvg([3,7,2]). • Avoids repetition of code. listAvg([3.0,7.0,2.0]) • E.g. We have a function to traverse a list and add all the sumList([3.0,7.0,2.0]) /. (float_of_int) length([3.0,7.0,2.0]) elements up. We also have a function to traverse a list and (3.0 +. SumList([7.0,2.0])) /. (float_of_int) (1 + Length([7.0,2.0])) multiply all the elements together. Why not have a function to traverse a list and apply some action, and make the action (3.0 +. (7.0 +. SumList([2.0]))) /. (float_of_int) (1 + (1 + Length([2]))) (function) a parameter? (3.0 + (7.0 + 2.0)) /. (float_of_int) (1 + (1 + (1 + Length(nil)))) (3.0 + 9.0) /. (float_of_int) (1 + (1 + (1 + 0))) • This is a natural feature of functional languages. 12.0 /. (float_of_int) (1 + (1 + 1)) • Functions can have functions as parameters. 12.0 /. (float_of_int) (1 + 2) 12.0 /. 3.0 4.0 21 22 6. Higher-Order Functions (continued) 7. Types • Example (The simplistic story) let rec doubleList l = match l with | [ ] -> [ ] | h :: t -> double(h) :: doubleList t;; Static Types: • All variables and parameters must have their types declared in let rec squareList l = match l with | [ ] -> [ ] the program, so that they can be checked by the compiler.