(Functional Programming) Reference: R.Sebesta, Chapter 15 COS220 Concepts of PLs AUBG, COS dept Lecture 52 Programming Styles (Functional Programming) Reference: R.Sebesta, Chapter 15 9/5/2018 Assoc. Prof. Stoyan Bonev
Introduction to FP Imperative programming vs. functional programming Language applied to functional programming is LISP – LISt Programming. It was invented to provide language features for list processing, the need for which grew out of the first application in the area of AI, expert systems, knowledge based systems. LISP – J.McCarthy, MIT, 1958 Lisp has two main descendants: Scheme–Sussman, MIT, 1975; Common Lisp, 1984 Related languages: ML, LCF, Miranda, Haskell 9/5/2018 Assoc. Prof. Stoyan Bonev
Lisp source illustrated A function call is written as a list with the function name or operator's name first, and the arguments following: Imperative style Functional style f(x, y, z); 9/5/2018 Assoc. Prof. Stoyan Bonev
Lisp source illustrated A function call is written as a list with the function name or operator's name first, and the arguments following: Imperative style Functional style f(x, y, z); (f x y z) 9/5/2018 Assoc. Prof. Stoyan Bonev
Lisp source illustrated A function call is written as a list with the function name or operator's name first, and the arguments following: Imperative style Functional style f(x, y, z); (f x y z) sqrt(a); 9/5/2018 Assoc. Prof. Stoyan Bonev
Lisp source illustrated A function call is written as a list with the function name or operator's name first, and the arguments following: Imperative style Functional style f(x, y, z); (f x y z) sqrt(a); (sqrt a) 9/5/2018 Assoc. Prof. Stoyan Bonev
Lisp source illustrated A function call is written as a list with the function name or operator's name first, and the arguments following: Imperative style Functional style f(x, y, z); (f x y z) sqrt(a); (sqrt a) 10 + 20 9/5/2018 Assoc. Prof. Stoyan Bonev
Lisp source illustrated A function call is written as a list with the function name or operator's name first, and the arguments following: Imperative style Functional style f(x, y, z); (f x y z) sqrt(a); (sqrt a) 10 + 20 (+ 10 20) 9/5/2018 Assoc. Prof. Stoyan Bonev
Lisp source illustrated A function call is written as a list with the function name or operator's name first, and the arguments following: Imperative style Functional style f(x, y, z); (f x y z) sqrt(a); (sqrt a) 10 + 20 (+ 10 20) gcd(a+b, c*d*e); 9/5/2018 Assoc. Prof. Stoyan Bonev
Lisp source illustrated A function call is written as a list with the function name or operator's name first, and the arguments following: Imperative style Functional style f(x, y, z); (f x y z) sqrt(a); (sqrt a) 10 + 20 (+ 10 20) gcd(a+b, c*d*e); (gcd (+ a b) (* c d e)) 9/5/2018 Assoc. Prof. Stoyan Bonev
Assoc. Prof. Stoyan Bonev What is FP? FP is a specific programming style in which: 1/ to write a functional program means to define a function or a set of functions; 2/ the only activity performed at run time is the function call statement. Pure FP is a programming style with - no memory allocation; - no assignment statements; - no loops, no iterative statements; - no flow charts; - no imperative (procedure) algorithms. 9/5/2018 Assoc. Prof. Stoyan Bonev
Corner stones to evaluate FP λ-calculus (after A. Church) The LISP PL (invented by J.McCarthy) John Backus and his paper “Can Programming be Liberated from the von Neumann Style? A Functional Style and its Algebra of Programs.”, Com of the ACM, vol21, no8, pp613-641 9/5/2018 Assoc. Prof. Stoyan Bonev
Functional Programming COMPOSITION OF FUNCTIONS = PROGRAMS 9/5/2018 Assoc. Prof. Stoyan Bonev
Assoc. Prof. Stoyan Bonev Basic principles of FP Successful Functional Programming needs: a fixed set of base, primitive, standard, generic functions; a mechanism to build new more powerful functions using formerly defined functions or base set of available functions. 9/5/2018 Assoc. Prof. Stoyan Bonev
Assoc. Prof. Stoyan Bonev Examples Given a base set function: max(x,y) Task1: compose a function that returns the greatest among three arguments greatest(a,b,c) max(a, max(b,c)) max(max(a,b), c) max(b, max(a,c)) 9/5/2018 Assoc. Prof. Stoyan Bonev
Assoc. Prof. Stoyan Bonev Examples Given a base set function: max(x,y), greatest(x,y,z) Task2: compose a function that returns the greatest among six arguments max(greatest(a,b,c), greatest(d,e,f)) greatest(max(a,b), max(c,d), max(e,f)) 9/5/2018 Assoc. Prof. Stoyan Bonev
Assoc. Prof. Stoyan Bonev So, for FP we need: 1/ base set of functions; 2/ mechanism for function composition; 3/ nothing else. Requirements to the base set of functions: - effective machine implementation; - to be easy for use. 9/5/2018 Assoc. Prof. Stoyan Bonev
Assoc. Prof. Stoyan Bonev So, for FP we need: For example, the base set should include functions for arithmetic operators, like add(x,y) x + y sub(x,y) x - y mul(x,y) x * y div(x,y) x / y Using these four functions, it’s possible an arbitrary expression to present in functional notation a+b*c (2*x + 3*y) / (x-4) 9/5/2018 Assoc. Prof. Stoyan Bonev
Assoc. Prof. Stoyan Bonev So, for FP we need: add(x,y) x + y sub(x,y) x - y mul(x,y) x * y div(x,y) x / y a+b*c is to be transformed to add(a, mul(b,c) ) 9/5/2018 Assoc. Prof. Stoyan Bonev
Assoc. Prof. Stoyan Bonev So, for FP we need: add(x,y) x + y sub(x,y) x - y mul(x,y) x * y div(x,y) x / y (2*x + 3*y) / (x-4) is to be transformed to div( add( mul(2,x), mul(3,y)) , sub(x,4) ) 9/5/2018 Assoc. Prof. Stoyan Bonev
Intro to LISP and its dialects
Intro to LISP and its dialects Before we comment LISP syntax (S-expressions, atoms, base set of functions) we’ll remind the List data structure. List is a basic data structure. It is the only data structure available in LISP to describe, present and store program code and data. Pure LISP data structures: atoms and lists: Atoms are symbols that have the form of identifiers or numeric constants; Lists are specified by surrounding/delimiting their elements within parentheses. 9/5/2018 Assoc. Prof. Stoyan Bonev
Lists Simple lists, in which elements are restricted to be only atoms, have the form ( A B C D ) Nested list structures are specified same way ( A ( B C ) D ( E ( F G ) ) ) The internal representation may be illustrated on the white board. 9/5/2018 Assoc. Prof. Stoyan Bonev
LISP syntax-model of simplicity Program code and Program data in Lisp have exactly the same form: parenthesized list. Consider the list: ( A B C D ) When interpreted as data, it is a list of four elements (data items). When viewed as code, it is the application of function named A to its three arguments B, C, and D. 9/5/2018 Assoc. Prof. Stoyan Bonev
The LISP machine infinite loop
The LISP machine infinite loop Most popular LISP machines (Scheme, Clisp) are implemented as an interpreter that operates as infinite loop performing the following three actions: Read-Eval-Print Loop or REPL Read; Evaluate; Write. Shortly the Lisp machine repeatedly: 1/ reads an expression typed by the user as a list except literals and names. 2/ interprets (evaluates) the expression. 3/ displays the resulting value. 9/5/2018 Assoc. Prof. Stoyan Bonev
Dialog using the LISP machine A/ input – numeric literal =>312 cr 312 9/5/2018 Assoc. Prof. Stoyan Bonev
Dialog using the LISP machine A/ input – numeric literal =>312 cr 312 B/ input – expression as a call to primitive functions in a list form. Expressions presented in prefix notation called Cambridge Polish notation Example: Ask the Lisp machine to calculate infix expression 220+370 or in other words to evaluate the expression =>(+ 220 370 ) 590 9/5/2018 Assoc. Prof. Stoyan Bonev
Dialog using the LISP machine A/ input – numeric literal =>312 cr 312 B/ input – expression as a call to primitive functions in a list form. Expressions presented in prefix notation called Cambridge Polish notation =>(+ 220 370 ) 590 =>(- 90 64 ) 26 9/5/2018 Assoc. Prof. Stoyan Bonev
Dialog using the LISP machine A/ input – numeric literal =>312 cr 312 B/ input – expression as a call to primitive functions in a list form. Expressions presented in prefix notation called Cambridge Polish notation =>(+ 220 370 ) 590 =>(- 90 64 ) 26 =>(* 25 8 ) 200 9/5/2018 Assoc. Prof. Stoyan Bonev
Dialog using the LISP machine A/ input – numeric literal =>312 cr 312 B/ input – expression as a call to primitive functions in a list form. Expressions presented in prefix notation called Cambridge Polish notation =>(+ 220 370 ) 590 =>(- 90 64 ) 26 =>(* 25 8 ) 200 =>(/ 10 2 ) 5 9/5/2018 Assoc. Prof. Stoyan Bonev
Assoc. Prof. Stoyan Bonev Combination List prefix notations like the examples just covered are called combination(s). The leftmost list element is the operator. The rest list elements are the operands. Two advantages of using such a notation: It permits to describe procedures with an arbitrary number of arguments (operands). =>(+ 22 44) =>(+ 3 5 7) =>(+ 11 22 33 44) 66 15 110 It permits to embed combinations as arguments. =>(+ (* 3 5 ) (- 10 6) ) 19 No restrictions on the level of embedding. 9/5/2018 Assoc. Prof. Stoyan Bonev
Assoc. Prof. Stoyan Bonev Using names in FP Imperative programming: Names are specified using statements to define, declare, initialize, and assign values to variables. FP: Names are specified using special form of a base function. In Scheme it is named define. In Clisp it is named setq. =>(define size 12) size It is said, that name size is bound to value of 12. In general, in its simplest form define serves to bind a symbol to the value of an expression. ( define symbol expression ) 9/5/2018 Assoc. Prof. Stoyan Bonev
Assoc. Prof. Stoyan Bonev More examples =>( define size 2 ) size 9/5/2018 Assoc. Prof. Stoyan Bonev
Assoc. Prof. Stoyan Bonev More examples =>( define size 2 ) size =>( define pi 3.1415 ) pi 9/5/2018 Assoc. Prof. Stoyan Bonev
Assoc. Prof. Stoyan Bonev More examples =>( define size 2 ) size =>( define pi 3.1415 ) pi =>( define two_pi ( * 2 pi ) ) two_pi 9/5/2018 Assoc. Prof. Stoyan Bonev
Assoc. Prof. Stoyan Bonev More examples =>( define size 2 ) size =>( define pi 3.1415 ) pi =>( define two_pi ( * 2 pi ) ) two_pi =>( define rad 10 ) rad 9/5/2018 Assoc. Prof. Stoyan Bonev
Assoc. Prof. Stoyan Bonev More examples =>( define size 2 ) size =>( define pi 3.1415 ) pi =>( define two_pi ( * 2 pi ) ) two_pi =>( define rad 10 ) rad =>( * 5 size ) 10 9/5/2018 Assoc. Prof. Stoyan Bonev
Assoc. Prof. Stoyan Bonev More examples =>( define size 2 ) size =>( define pi 3.1415 ) pi =>( define two_pi ( * 2 pi ) ) two_pi =>( define rad 10 ) rad =>( * 5 size ) 10 =>( * pi ( * rad rad ) ) 314.15 9/5/2018 Assoc. Prof. Stoyan Bonev
Assoc. Prof. Stoyan Bonev More examples =>( define size 2 ) size =>( define pi 3.1415 ) pi =>( define two_pi ( * 2 pi ) ) two_pi =>( define rad 10 ) rad =>( * 5 size ) 10 =>( * pi ( * rad rad ) ) 314.15 =>( * pi ( * size rad ) ) 62.83 9/5/2018 Assoc. Prof. Stoyan Bonev
Assoc. Prof. Stoyan Bonev More examples (cont.) =>( define circlearea ( * pi rad rad ) ) circlearea 9/5/2018 Assoc. Prof. Stoyan Bonev
Assoc. Prof. Stoyan Bonev More examples (cont.) =>( define circlearea ( * pi rad rad ) ) circlearea =>circlearea 314.15 9/5/2018 Assoc. Prof. Stoyan Bonev
Assoc. Prof. Stoyan Bonev More examples (cont.) =>( define circlearea ( * pi rad rad ) ) circlearea =>circlearea 314.15 =>( define circlelen ( * two_pi rad ) ) circlelen 9/5/2018 Assoc. Prof. Stoyan Bonev
Assoc. Prof. Stoyan Bonev More examples (cont.) =>( define circlearea ( * pi rad rad ) ) circlearea =>circlearea 314.15 =>( define circlelen ( * two_pi rad ) ) circlelen =>circlelen 62.83 9/5/2018 Assoc. Prof. Stoyan Bonev
Functions for constructing functions In Scheme User defined functions are described using the same base primitive function define. In this form define takes two lists as parameters. The first is the prototype of a function call with the function name followed by formal parameters, all in a list. The second list is the expression to which the name is to be bound. ( define ( <function_name> <parameters> ) <body> ) <parameters> are separated by space(s), not by comma(s) and the <body> is a sequence of expressions, all presented in form of lists. 9/5/2018 Assoc. Prof. Stoyan Bonev
Functions for constructing functions In Clisp User defined functions are described using the base primitive function defun. In this form defun precedes the function name and two lists. The first list includes the function parameters. The second list is the expression to which the name is to be bound. ( defun <function_name> ( <parameters> ) <body> ) <parameters> are separated by space(s), not by comma(s) and the <body> is a sequence of expressions, all presented in form of lists. 9/5/2018 Assoc. Prof. Stoyan Bonev
Assoc. Prof. Stoyan Bonev Examples ( define ( <function_name> <parameters> ) <body> ) ( define ( sqr x ) ( * x x ) ( define ( cube x ) ( * x x x ) ( define ( reciproc x ) ( / 1 x ) 9/5/2018 Assoc. Prof. Stoyan Bonev
Using the functions defined Explicit call for expression calculation =>(sqr 15) =>(sqr 21) =>(sqr (sqr 3)) 225 441 81 9/5/2018 Assoc. Prof. Stoyan Bonev
Using the functions defined Explicit call for expression calculation =>(sqr 15) =>(sqr 21) =>(sqr (sqr 3)) 225 441 81 New functions definition =>(define (sum_of_squares x y) (+ (* x x) (* y y ) ) ) sum_of_squares 9/5/2018 Assoc. Prof. Stoyan Bonev
Using the functions defined Explicit call for expression calculation =>(sqr 15) =>(sqr 21) =>(sqr (sqr 3)) 225 441 81 New functions definition =>(define (sum_of_squares x y) (+ (* x x) (* y y ) ) ) sum_of_squares =>(sum_of_squares 3 4 ) 25 9/5/2018 Assoc. Prof. Stoyan Bonev
Using the functions defined Explicit call for expression calculation =>(sqr 15) =>(sqr 21) =>(sqr (sqr 3)) 225 441 81 New functions definition =>(define (sum_of_squares x y) (+ (* x x) (* y y ) ) ) sum_of_squares =>(sum_of_squares 3 4 ) 25 =>(define ( f a ) (sum_of_squares (+ a 1) (* a 2 ) ) ) f 9/5/2018 Assoc. Prof. Stoyan Bonev
Using the functions defined Explicit call for expression calculation =>(sqr 15) =>(sqr 21) =>(sqr (sqr 3)) 225 441 81 New functions definition =>(define (sum_of_squares x y) (+ (* x x) (* y y ) ) ) sum_of_squares =>(sum_of_squares 3 4 ) 25 =>(define ( f a ) (sum_of_squares (+ a 1) (* a 2 ) ) ) f =>(f 5) 136 9/5/2018 Assoc. Prof. Stoyan Bonev
Assoc. Prof. Stoyan Bonev Control flow The computational power of user defined functions may increase if we introduce a control flow mechanism instead providing function calls for linear algorithms. Let me remind the McCarthy’s conditional expression [b1->e1,b2->e2, … bn-1->en-1,en] and its LISP notation in three versions 9/5/2018 Assoc. Prof. Stoyan Bonev
Assoc. Prof. Stoyan Bonev First version ( cond ( <b1> <e1> ) ( <b2> <e2> ) . . . ( <bn-1> <en-1> ) ( <bn> <en> ) ) 9/5/2018 Assoc. Prof. Stoyan Bonev
Assoc. Prof. Stoyan Bonev Second version ( cond ( <b1> <e1> ) ( <b2> <e2> ) . . . ( <bn-1> <en-1> ) ( else <en> ) ) 9/5/2018 Assoc. Prof. Stoyan Bonev
Assoc. Prof. Stoyan Bonev Third version ( if <predicate> <then-expression> <else-expression> ) 9/5/2018 Assoc. Prof. Stoyan Bonev
Using conditional expressions To define function abs(x) = x, if x>0 = 0, if x=0 = -x, if x<0 ( define ( abs x ) ( cond ( (> x 0 ) x ) ( (= x 0 ) 0 ) ( (< x 0 ) ( - x) ) ) 9/5/2018 Assoc. Prof. Stoyan Bonev
Assoc. Prof. Stoyan Bonev Two more versions ( define ( abs x ) ( cond ( (< x 0 ) ( - x) ) ( else x ) ) 9/5/2018 Assoc. Prof. Stoyan Bonev
Assoc. Prof. Stoyan Bonev Two more versions ( define ( abs x ) ( cond ( (< x 0 ) ( - x) ) ( else x ) ) ( if (< x 0) (- x) x ) 9/5/2018 Assoc. Prof. Stoyan Bonev
Assoc. Prof. Stoyan Bonev Logical expressions Example 1: 5 < x < 10 9/5/2018 Assoc. Prof. Stoyan Bonev
Assoc. Prof. Stoyan Bonev Logical expressions Example 1: 5 < x < 10 (and (> x 5) (< x 10) ) 9/5/2018 Assoc. Prof. Stoyan Bonev 61
Assoc. Prof. Stoyan Bonev Logical expressions Example 2: define own predicate >= (define (>= x y ) (or (> x y) (= x y) ) ) OR (define (>= x y ) (not (< x y) ) ) 9/5/2018 Assoc. Prof. Stoyan Bonev
Assoc. Prof. Stoyan Bonev Recursion in LISP Function returns sum of n natural numbers Imperative (C/C++) version: int sumr(int n){ if (n==0) return n; else return n + sumr(n-1); } Functional Lisp list version: (define (sumr n) ( if (= n 0) 0 (+ n (sumr (- n 1) ) ) ) ) 9/5/2018 Assoc. Prof. Stoyan Bonev
List Processing in LISP
Assoc. Prof. Stoyan Bonev LISP syntax To specify a list: ( A B C D ) function call A(B,C,D) ‘( A B C D ) list of four data elements To bind a name to a list ( define lis ‘(A B C D )) ( setq lis ‘(A B C D )) 9/5/2018 Assoc. Prof. Stoyan Bonev
Primitive list selectors List selector car. car returns the first element (head) of a list (car ‘(A B C D )) returns A (car ‘((A B) C D)) returns (A B) (car ‘A) is an error (car ‘(A)) returns A 9/5/2018 Assoc. Prof. Stoyan Bonev
Primitive list selectors List selector cdr. cdr returns the remainder of a list after its car is removed (cdr ‘(A B C D )) returns (B C D) (cdr ‘((A B) C D)) returns (C D) (cdr ‘A) is an error (cdr ‘(A)) returns ( ) – empty list 9/5/2018 Assoc. Prof. Stoyan Bonev
Primitive list constructor List constructor cons. cons builds a list using its two parameters (cons ‘A ‘() ) returns (A) (cons ‘A ‘(B C) ) returns (A B C) (cons (car lis) (cdr lis) ) returns lis 9/5/2018 Assoc. Prof. Stoyan Bonev
Primitive list predicates null(<argument>) Returns T (true) if argument is an empty list atom(<argument>) Returns T (true) if argument is an atom eq(<argument> <argument>) Returns T (true) if both arguments are the same, otherwise NIL (false) 9/5/2018 Assoc. Prof. Stoyan Bonev
Definition of functions on lists Function to return the length of a list ( define (len x) (if (null x) (+ 1 (len (cdr x) ) ) ) 9/5/2018 Assoc. Prof. Stoyan Bonev
Definition of functions on lists Function to return the length of a list ( defun len (x) (if (null x) (+ 1 (len (cdr x) ) ) ) 9/5/2018 Assoc. Prof. Stoyan Bonev
Definition of functions on lists Function to return the length of a list ( setq lis ‘(A B C D) ) Function call ( len lis ) returns 4 9/5/2018 Assoc. Prof. Stoyan Bonev
Thank You For Your Attention