820 likes | 1.03k Views
Coverage. Introduction to Functional Languages LISP Scheme ML Haskell Functional Language Programming. Introduction. Imperative Vs Functional languages Imperative: Based on Von Neumann architecture. Functional: Not based on architecture, mathematically based, based on lambda calculus
E N D
Coverage • Introduction to Functional Languages • LISP • Scheme • ML • Haskell • Functional Language Programming Functional Languages
Introduction • Imperative Vs Functional languages • Imperative: Based on Von Neumann architecture. • Functional: Not based on architecture, mathematically based, based on lambda calculus • Example of functional languages: LISP, Scheme, Haskell, ML, … • LISP: Used for artificial intelligence • Scheme is mostly taught as an introductory functional language Functional Languages
Introduction • Mathematical functions • Provide a mapping of members of one set called the domain set to that of another set called the range set • (x) x * x * x for the function cube (x) = x * x * x • Lambda expressions are used to describe nameless functions and apply the parameters that are present after the expression • ((x) x * x * x)(3) evaluates to 27 • Functional Forms or First-Class objects (Higher-order function or functionals): • Takes one or more functions as parameters or yields a function as its result or both • Higher-order functions that return other functions are called as curried • First-order functions: arguments and results are not functions; Second-order function takes first-order function as an argument; Third-order function takes second-order function as an argument Functional Languages
Introduction • Functional Composition: A functional form that takes two functions as parameters and yields a function whose value is the first actual parameter function applied to the application of the second. This is represented as: h f ° g • which means h (x) f ( g ( x)) • For f (x) x * x * x and g (x) x + 3, • h f ° g yields (x + 3)* (x + 3)* (x + 3) • Construction: A functional form that takes a list of functions as parameters and yields a list of the results of applying each of its parameter functions to a given parameter. • This is represented as: [f, g] • For f (x) x * x * x and g (x) x + 3, • [f, g] (4) yields (64, 7) Functional Languages
Introduction • Apply-to-all: A functional form that takes a single function as a parameter and yields a list of values obtained by applying the given function to each element of a list of parameters. This is represented as: • For h (x) x * x * x • ( h, (3, 2, 4)) yields (27, 8, 64) Functional Languages
Fundamentals of Functional Languages • Called as applicative or expression-oriented programming language • Aimed to mimic mathematical functions • Used in Artificial Intelligence, Mathematical Proof Systems, Logic, and Parallel Processing Applications • Functional languages don't perform operations and store the results in variables for later use • X = X + 1 is not allowed mathematically and thus not allowed in functional languages • Loops are handled in functional languages using recursion. • Functional languages lack variables, assignments, loop and iteration but support constants, parameters and recursion. • Functional languages that support variables, assignments and looping are considered to be not part of the "pure" functional programming. Functional Languages
Fundamentals of Functional Languages • Variable Types: • LISP and Scheme: values have types but not the variables • Type checking is the process of checking whether the given atom or element is a list or function or whatever in the specified language. Type checking is done at run-time • Scope of a variable (dynamic scope or lexical scope) • Lexical scope (static scope): scope of the variable is determined by the location at which the variable is declared in the program itself • Dynamic scope: scope of the variable based on the flow of the execution of the program • By default, LISP and Scheme use Lexical scope • Common LISP do support dynamic scope along with lexical scoping. Functional Languages
Fundamentals of Functional Languages • Evaluation of Expressions: • Expressions can be evaluated selectively, recursively or using short-circuit evaluation. • Short-circuit evaluation or minimal evaluation: In an expression with Boolean operators (and, or, …), the second argument is evaluated only if the first argument is not sufficient to make the conclusion • LISP, Scheme and Haskell do perform short-circuit evaluation • Function Handling: • Referential transparency: function evaluations always produce the same result given the same parameters • There are no side effects as the current evaluation of a function depends only on the current values and not on any previous computation or even the order of the evaluation of its parameters Functional Languages
Fundamentals of Functional Languages • Eager Evaluation: • Arguments to a function are normally evaluated at the time of the call and each argument passed to a function is evaluated only once • Lazy Evaluation: • An argument to a function is not evaluated until it is really needed and the argument is re-evaluated each time it is needed, which may be more than once • Set of primitives: • Predefined by the language as basic functions and correspond to built-in operations of imperative language • Application Operation: • Application Operation indicates applying a function to its arguments and producing a value as the result. Functional Languages
Fundamentals of Functional Languages • Set of data objects: • Data objects are allowed members of the domain and range sets • Atomic objects (atoms) form the basis for the composition of compound objects. Atomic objects are those base objects which can not be subdivided further on. They could only to be combined to form compound objects. • Atoms include integers, floating-point numbers and symbolic atoms. • Symbolic atoms could be made of more than one character but they are not further divided and so is part of atoms. • Binding names to functions: • Binding names to functions indicate how to denote names to the new functions. • Memory allocation of functional languages is totally automatic called as Dynamic Memory Management. Functional Languages
LISP (LISt Processing) • LISP is a typeless language • Data object types: • Atoms and lists • List is represented using parenthesized collection of sublists and/or atoms as: (A B (C D) E). LISP lists are stored internally in the system as single-linked lists. • The heart of the execution of any LISP program is called as the evaluator. Evaluator expects the program to be already expanded before being asked it to be executed. • Uses lambda notations • if the list (A B C) is interpreted as data it is a simple list of three atoms, A, B, and C. • If it is interpreted as a function application, it means that the function named A is applied to the two parameters, B and C. Functional Languages
LISP (LISt Processing) • LISP is a typeless language • Data object types: • Atoms and lists • List is represented using parenthesized collection of sublists and/or atoms as: (A B (C D) E). LISP lists are stored internally in the system as single-linked lists. • The heart of the execution of any LISP program is called as the evaluator. Evaluator expects the program to be already expanded before being asked it to be executed. • Uses lambda notations • if the list (A B C) is interpreted as data it is a simple list of three atoms, A, B, and C. • If it is interpreted as a function application, it means that the function named A is applied to the two parameters, B and C. Functional Languages
LISP (LISt Processing) • Rules to denote mathematical operators: • Notation followed should be prefix notation. • All operators must be within parenthesis. • The order of operations must be clarified using parenthesis. • A space must appear between operators and operands. • LISP interpreter environment is called as read-eval-print loop because it reads input, then evaluates the expression and then prints the result in an infinite loop fashion • Dialects: Lisp 1.5, Maclisp, CommonLisp, … • LISP assumes that anything that appears immediately after the parenthesis is the function and those that follow are arguments. • (+ 1 2 3) • (+ (* 2 3) (* 4 5)) • (f x y) Functional Languages
LISP (LISt Processing) • LISP is a case insensitive language • Comments in LISP are indicated using a semi-colon • Examples provided are tested using Common LISP implementation (clisp-2.32) • (+ 4 5) ; expression will be evaluated to a value 9 • (+ (+ 1 2) (+ 4 5)) ; evaluates 1+2, then 4+5, then 3+9 to get value • (quote alphabet) ; output of this function is ALPHABET • ; converts the word in to capital letters • (cons (quote A) (quote B)) ; pair of atoms A and B • (quote (+ 1 2)) ; evaluates to form a list as (+ 1 2) • '(+ 1 2) ; same as (quote (+ 1 2)) • The difference between (+ 1 2) and (quote (+ 1 2)) is that the addition function is not evaluated when quote is used. The quote function converts the given elements into a list form. • (car '(1 (2 3) 4)) ; returns 1 • ; returns the head of the given list. Functional Languages
LISP (LISt Processing) • (cdr '(1 (2 3) 4)) ; ((2 3) 4) • ; returns all elements except head of the given list. • (atom '(1 2)) ; Returns False because a list is given. • List is different from atom because atom is a single element and list is a collection of elements. • (atom '(1)) ; Returns False because a list with a single element is given. • (atom 1) ; True as 1 is an atom. • (atom a) ; An error is returned because a is not defined. • (atom 'a) ; True as a is an atom. • Single quote in front of the list is necessary so that LISP does not try to evaluate it as an argument. • (cons '1 '(2 3 a 4)) ; Returns (1 2 3 a 4) • ; does concatenation Functional Languages
LISP (LISt Processing) • Let's see certain examples with various functions. • (/ (- 25 3) (- 12 5)) ; Returns 3.14286 • (max 1 2 3) ; Returns 3 • ; Returns the maximum element (lists not allowed) • (min 1 2 3) ; Returns 1 • (sqrt 2) ; Returns the square root - Returns 1.414.. • (expt 2 3) ; Returns baseexponent - Returns 8 • (setq a 5) ; store a number as the value of a symbol 5 • a ; take the value of a symbol 5 • (setq list1 '(1 2)) • (setq list2 '(1 2)) • (equal list1 list2) ; Returns t • (eq list1 list2) ; Returns NIL, as they don't represented same memory • (let ((a 6)) a) ; bind the value of a symbol temporarily to 6 • a ; the value returns to 5 once the let is finished 5 • (+ a 6) ; use the value of a symbol as an argument to a function 11 Functional Languages
LISP (LISt Processing) • (let ((x 1) (y (+ x 1))) y ) • This will cause an error because an attempt is made to take the value of the symbol y is not defined. • (let ((x 1)) (+ x 1)) ; Returns 2 • If the symbol x already has a global value, strange happenings will result: • (setq x 7) ; 7 • (let ((x 1) (y (+ x 1))) y ) ; 8 • (let ((x 1)) (y (+ x 1)) y ) ; Returns an error with regards to y. • The let* function is a special form, is just like let except that it allows values to reference variables defined earlier in the let*. In let*, the (<variable> <init>) binding expression is valid until the end of the let*. Let function evaluates the function in parallel while let* evaluates the function sequentially. • (setq x 7) ; 7 • (let* ((x 1) (y (+ x 1))) y ) ; 2 • Here, the initial value of x = 7 is overwritten by a later value of x = 1. Functional Languages
LISP (LISt Processing) • Backquote in LISP: • (setq x 5) ; Setting x as 5 • `(if x is true (or x x) then) ; Returns (if x is true (or x x) then) • `(if ,x is true (or ,x x) then) ; Returns (if 5 is true (or 5 x) then) • ; Use of quote will generate an error. Use backquote instead • ; Usage of comma requires backquote and not quote • ; Also there is no space between comma and variable • ; Comma is meant for variable (x) and not to divide or and x. • `(if ,x is true ,(or x x) then) ; Returns (if 5 is true 5 then) • (list 'if x 'is 'true (list x x) 'is 'true) ; Returns (if 5 is true (5 5) is true) • (list 'if x 'is 'true (or x x) 'is 'true) ; Returns (if 5 is true 5 is true) • (setq y '(1 2 3)) ; Setting y as (1 2 3) • `(hello test ,y) ; Returns (hello test (1 2 3)) • ; Note: Make sure backquote is used and not quote. • '(hello test ,@y) ; Returns (hello test 1 2 3) Functional Languages
LISP (LISt Processing) • List Manipulation in LISP: • (list 5) ; Converts the given list into a list - Returns (5) • (list '5) ; Returns (5) – no difference with or without quote • (list 5 6) ; Returns (5 6) • (first '(1 2 3)) ; Returns the first element of the list – Returns 1 • (second '(1 2 3)) ; Returns the second element of the list – Returns 2 • ; Can do the above until the tenth element of the list • (nth 2 '(1 2 3)) ; Returns the third element of the list – Returns 3 • ; Note: Element numbering starts from 0 for nth function. • (nthcdr 2 '(1 2 3 4)) ; trims off n elements – Returns (3 4) • (butlast '(1 2 3)) ; trims off the last element of the list – Returns (1 2) • (butlast '(1 2 3) 2) ; trims off last 2 elements of the list – Returns (1) • (last '(1 2 3)) ; Returns the last element of the list – Returns (3) • (length '(1 2 3)) ; Returns the length of the list – Returns 3 • (length '(1 2 (3 4))) ; Inner list elements are not counted – Returns 3 • (null '(1 2 3)) ; Checks if the list is empty - Returns NIL • (endp ()) ; Returns T; endp checks whether the list is empty or not. Functional Languages
LISP (LISt Processing) • List Manipulation in LISP: • (append '(1 2) '(3 4)) ; Returns (1 2 3 4) • (nconc '(1 2) '(3 4)) ; Returns (1 2 3 4) • (rplaca xy) changes the car of x to y and returns (the modified) x. x must be a cons, but y may be any LISP object. We could write the same as (cons y (cdr x)). • (setq g '(a b c)) • (rplaca (cdr g) 'd) ; Now g => (d c) • (rplacd xy) changes the cdr of x to y and returns (the modified) x. x must be a cons, but y may be any LISP object. • (setq x '(a b c)) • (rplacd x 'd) ; Now x => (a . d) • Association Lists: Association lists allow for the definition of mappings like mapping a variable m to ((1 one) (2 two) (3 three) …). • (setq m '((1 one) (2 two) (3 three))) • (assoc '2 m) ; Returns (2 Two) • (setq m '((1 . one) (2 . two) (3 . three))) • (assoc '2 m) ; Returns (2 . Two) Functional Languages
LISP (LISt Processing) • Property Lists: Property list is used to establish relations between atoms and lists. Generally, this is handled using put and get in LISP as below: • (put 'mary 'age 21) ; 21 • (put ‘mary 'child 'sam) ; sam • (put 'sam 'child 'bob) ; bob • (get 'mary 'age) ; 21 • (get (get 'mary 'child) 'child) ; bob • The equivalent for the above property list in clisp (LISP software used in this chapter) is as below: • (setf (get 'mary 'age) 21) ; 21 • (setf (get ‘mary 'child) 'sam) ; sam • (setf (get 'sam 'child) 'bob) ; bob • (get 'mary 'age) ; 21 • (get (get 'mary 'child') 'child) ; bob • As put is not supported in clisp, instead of put we need to use setf. Functional Languages
LISP (LISt Processing) • Control Structures • (cond (p1 e1) ... (pn en) ) • Proceeds from left to right and find the value of p1 and then if it is true, it evaluates e1. • (cond ((< 2 1) 2) ((< 1 2) 1)) ; has value 1 • (cond ((< 2 1 ) 2) ((< 3 2) 3)) ; has no value • Another representation of if statement is: • (if t 5 6) ; Returns 5 • Do Loop: • (do ( (x 1 (+ x 1)) (y 1 (* y 2)) ) ((> x 5) y) (print x) (print 'working) ) • Initialization: Variable x is given a value of 1. Variable y is given a value of 1. • Increment option: Then x is incremented by 1. Then y is multiplied by 2. • Condition: If x is greater than 5, value of y is returned and the loop is stopped. Otherwise, value of x is printed. Each time, the word 'working' is printed. Within the loop, the increment option is handled. • To combine statements, use {}. Functional Languages
LISP (LISt Processing) • Case Statement: • (setq x 'b) ; Returns B • (case x (a 5) ((d e) 7) ((b f) 3) (otherwise 9) ) ; Returns 3 • The list (d e) indicates the matching of any element of the list. If none of the choices in the case statement is matched, then the otherwise choice will be matched. • When and unless Statement: • Functions when and unless, can have any number of statements within their bodies • Many statements can be included in the body of if statement using the reserved word "progn". For example, (when x a b c) is equivalent to (if x (progn a b c)). • (when t (setq a 5) (+ a 6) ) ; Returns 11 • (when nil (setq a 5) (+ a 6) ) ; Returns nil • (unless t (setq a 5) (+ a 6) ) ; Returns nil • (unless nil (setq a 5) (+ a 6) ) ; Returns 11 Functional Languages
LISP (LISt Processing) • progn takes a number of forms and evaluates them one after the other, from left to right. Only the final value is displayed. • (progn (setq a 5) (+ a 5)) ; Returns 10 • prog1 is another construct which is similar to that of progn but returns the value of the first form only. • (prog1 (setq a 5) (+ a 5)) ; Returns 5 • Logical and conditional operators in LISP: • (= 5 4) ; Checks for equal - Returns nil • (/= 5 4) ; Checks for not equal - Returns t • (> 5 4) ; Checks for greater than - Returns t • (and t nil) ; Returns nil • (or t nil) ; Returns t • (and (< 3 4) (> 6 5)) ; Returns t • (not nil) ; Returns t • (equal 4 4) ; Checks if the given values are equal - Returns t • (eq 4 4) ; Checks if the given values are equal and are represented by the same chunk of memory - Returns t Functional Languages
LISP (LISt Processing) • Type checking predicates in LISP: • A predicate is a function that tests for a condition. • A predicate will return nil if the condition is not met and t (or non-nil or true) otherwise. • As a convention, the predicates normally end with a letter p, which stands for predicate. • (symbolp +) ; Checks if the given argument is a symbol - Returns nil • (symbolp 'cat) ; Returns t • (numberp 1) ; Checks if the given value is a number - Returns t • (listp '(1 2)) ; Checks if the given value is a list - Returns t • (atom a) ; Checks if the given value is an atom - Returns t • (consp '(a b)) ; Opposite of (atom '(a b)) - Returns t • (floatp 4); Checks if the argument is a floating point number - Returns nil • (integerp 3) ; Checks if the argument is an integer - Returns t • (complexp #c(3 5)) ; Checks if the argument is a complex number - Returns t Functional Languages
LISP (LISt Processing) • Type checking predicates in LISP: • (characterp "abc") ; Checks if the argument is a character - Returns nil • (characterp #\a) ; Checks if the argument is a character - Returns t • (stringp "abc") ; Checks if the argument is a string - Returns t • (stringp 'abc') ; Returns an error • (functionp 'append) ; Checks if the argument is a function - Returns nil • (functionp #'append) ; Checks if the argument is a function - Returns t • (arrayp "hello") ; Checks if the argument is an array - Returns t • (arrayp (make-array '(1 2 3))) ; Checks if the argument is an array - Returns t • (bit-vector-p #*1010) ; Checks if the argument is a bit vector - Returns t • (simple-vector-p (make-array 4)) ; Checks if the argument is a vector - Returns t • (packagep 'common-lisp) ; Checks if the argument is a package - Returns nil Functional Languages
LISP (LISt Processing) • Structures in LISP: • (defstruct Name Slot1 Slot2 …) • (defstruct Student Course Grade) • (defstruct Student (Course "Compiler") (Grade "B")) ; With default values • defstruct function creates a function as make-Student that could accept keywords as :Course and :Grade. Also, slot lookup functions like Student-Course and Source-Grade, plus slot setting functions like (setf Student-Course) and (setf Student-Grade) are created. • (setq Bao (make-Student :Course "Computer Networks" :Grade "A")) • (Student-Course Bao) ; Returns "Computer Networks" • (setf (Student-Course Bao) "Distributed Computing") • (Student-Course Bao) ; Returns "Distributed Computing" • (type-of Bao) ; Returns STUDENT • (typep Bao `Student) ; Returns t as Bao is of structure Student Functional Languages
LISP (LISt Processing) • Macros in LISP: • Function calls are processed by the evaluator • As evaluator expects anything that is passed to it to be already expanded, macros might need to be expanded before sending to the evaluator or should be evaluated separately • All required macro definitions should be available to the interpreter or compiler before any call to macro. Otherwise, macro will also be treated as a function. • Macros cannot be passed as arguments to functions like apply, funcall or map. • Simple addition function and addition macro that just adds two numbers: • (defun addfun(a b) (+ a b)) • (defmacro addmacro(a b) `(+, a, b)) • Calling (addfun 1 2) and (addmacro 1 2) will return 3 • Macro processing is less time consuming than that of functions. Functions with in-line lambda expression take longer processing time. • setf and defstruct could be used with macros but not with functions. Functional Languages
LISP (LISt Processing) • Packages in LISP: • Packages are used to identify or refer to variables available in different packages. This means that we could access two different variables present in different namespaces but with the same name • The command (list-all-packages) is used to find all the packages present in your LISP • Reference to various variables present in different packages can be accessed using : or :: syntax • (make-package 'test1) ; Create a package named test1 • (make-package 'test2) ; Create a package named test2 • (in-package test1) ; Using package test1 • (defun test() "Test function in test1") ; Adding function to test1 package • (in-package test2) ; Using package test2 • (defun test() "Test function in test2") ; Adding function to test2 package • (test) ; Returns "Test function in test2" • (in-package test1) ; Using package test1 • (test) ; Returns "Test function in test1" • (test2::test) ; Returns "Test function in test2" Functional Languages
LISP (LISt Processing) • Packages in LISP: • (import `test2::test) ; Can't import as there is conflict with test() of test1 • (in-package test2) ; Using package test2 • (defun testing() "Testing function in test2") ; Testing function in test2 • (in-package test1) ; Using package test1 • (import `test2::testing) ; Returns t • (testing) ; Returns "Testing function in test2" • (unintern `test2::testing) ; Returns t and the import is removed • (testing) ; Returns an errors as import has been removed. • Sequences in LISP: • (defun inc (x) #'(lambda (x)) (+ x 2)) • ; Note that after Hash you must have a quote and not backquote • (mapcar 'inc '(1 2 3)) ; Returns (3 4 5) • (defun inc (x) #'(lambda (x) (+ x 2)) x) • (mapcar 'inc '(1 2 3)) ; Returns (1 2 3) • (defun inc (x) (+ x 1)) (mapcar 'inc '(1 2 3)) ; Returns (2 3 4) Functional Languages
LISP (LISt Processing) • Packages in LISP: • (import `test2::test) ; Can't import as there is conflict with test() of test1 • (in-package test2) ; Using package test2 • (defun testing() "Testing function in test2") ; Testing function in test2 • (in-package test1) ; Using package test1 • (import `test2::testing) ; Returns t • (testing) ; Returns "Testing function in test2" • (unintern `test2::testing) ; Returns t and the import is removed • (testing) ; Returns an errors as import has been removed. • Sequences in LISP: • (defun inc (x) #'(lambda (x)) (+ x 2)) • ; Note that after Hash you must have a quote and not backquote • (mapcar 'inc '(1 2 3)) ; Returns (3 4 5) • (defun inc (x) #'(lambda (x) (+ x 2)) x) • (mapcar 'inc '(1 2 3)) ; Returns (1 2 3) • (defun inc (x) (+ x 1)) (mapcar 'inc '(1 2 3)) ; Returns (2 3 4) Functional Languages
LISP (LISt Processing) • File Handling and Input/Output Functions in LISP: • Input Statements: • (setq n (read)) ; Reads input from the keyboard and assign it to n • Output Statements: • (prin1 "hello world") ; Prints the result of the expression and returns its value • (print "hello world") ; Similar to prin1 but adds a new line before the printed line • (princ "hello world") ; Similar to prin1 but prints the string within quotes • (print 3) ; 3 3 -- The first 3 above was printed, the second was returned. • (format t "An atom: ~S~%and a list: ~S~%and an integer: ~D~%" nil (list 5) 6) • ; An atom: NIL and a list: (5) and an integer: 6 NIL • First parameter of the format function can be t, nil, or a stream. "t" specifies output to the terminal. "Nil" means not to print anything but to return a string containing the output instead. Functional Languages
LISP (LISt Processing) • File Handling and Input/Output Functions in LISP: • File input: The file (filename.txt) is present in the current directory (In LISP software like clisp, it should be the full directory from where you have started LISP using lisp.exe –M lispinit.mem). • (setq fp (open "filename.txt" :direction :input)) • (read fp nil) ; displays first line • (read fp nil) ; displays second line • (read fp nil) ; If no more line, it returns nil • (setq fp (open "filename.txt" :direction :input)) • ; To repeat reading from the first line, issue this command again • (setq a (read fp nil)) ; Stores the file line to a variable a • To display the contents of the whole file (Note: do* is like let* to let, for do): • (do* ((fp (open "filename.txt" :direction :input)) • (ex (read fp nil) (read fp nil))) • ((null ex) nil) (print ex)) Functional Languages
LISP (LISt Processing) • Error Handling in LISP: • Error handling is done by looking for certain conditions or situations. • Occurrence of any error in the LISP program will force an entry into the debugger. • The simplest means of not entering into the debugging is using ignore-errors. • (open "test.txt" :direction :input) ; Returns an error that file does not exist • (ignore-errors (open "test.txt" :direction :input)) • ; No error message is reported • ; A NIL and the condition is displayed. • LISP’s condition system signals a condition, handles it and allows restarting • We should define our conditions as a subclass of error using: • (define-condition name-of-condition (error) ((text :initarg :text :reader text))) Functional Languages
LISP (LISt Processing) • Error Handling in LISP: • Equivalent to the ignore-errors, handler-case is provided which provides more detailed control of specific errors, including those like stack overflow that are of called as serious condition. ignore-errors do not handle serious conditions. • ; Generic format of handler-case is • (handler-case (main-action) (error (c) (other-action))) • (handler-case expression error-clause) • The error-clause is of the form: (condition-type ([var]) code) • ; The following is the equivalent of the previous ignore-errors • (handler-case (open "test.txt" :direction :input) • (error (c) (values nil c))) • To catch serious conditions, we have to use the following: • (handler-case (open "test.txt" :direction :input) • (serious-condition (c) (values nil c))) Functional Languages
LISP (LISt Processing) • Eval function is used to evaluate contents of the list • (defun substitute (x y z) (function (lambda (x y z) • (cond ((null z) z) ((atom z) • (cond ((eq z y) x ) (t z))) • (t (cons (substitute x y (car z)) (substitute x y (cdr z)))))))) • (defun substitute-test (x y z) (function (lambda (x y z) • (eval (substitute x y z))))) • Here, the output of the program returns a CLOSURE when run with any one of the following: • (substitute-test '3 'x '(+ x 1)) • (funcall * '3 'x '(+ x 1)) • This is because there is no output specified as the result of the function. • The above program could be changed as below: • (defun substitute (x y z) (function (lambda (x y z) )) • (cond ((null z) z) ((atom z) • (cond ((eq z y) x ) (t z))) • (t (cons (substitute x y (car z)) (substitute x y (cdr z)))))) • When the above is called with (substitute 1 2 '(1 2 3)), it returns (1 1 3). Thus y is replaced with x in z. Functional Languages
LISP (LISt Processing) • Memory Management and Garbage Collection (GC): • LISP uses both stack and heap • Linked list elements are stored onto the heap • Garbage collection is automatic and run at run-time • Garbage collection is done either by reference counting or mark-sweep approach Functional Languages
Scheme • Developed in mid-1970s • Scheme uses static scoping only • Scheme is a case sensitive language • Scheme uses a metacircular interpreter, which is an interpreter written in the language itself • Memory management is done automatically by runtime system • Comments are preceded with a semi-colon in Scheme • Programs are tested using DrScheme software • 52 ; a number • "hello" ; a string • #T ; the Boolean value "true" • #\a ; the character 'a' • (3.1 3.2 3.1) ; a list of numbers • a ; an identifier • (+ 2 5) ; list consisting of the identifier "+" and two numbers Functional Languages
Scheme • Arithmetic: • (+ 5 2) ; Returns 7 • (+) ; Returns 0 • (+ 5) ; Returns 5 • (+ 1 2 3) ; Returns 6 • (abs -5) ; Returns 5 • (sqrt 2) ; Returns 1.414 • (remainder 5 3) ; Returns 2 • (min 2 3 4) ; Returns 2 • (max 2 3 4) ; Returns 4 • quote: Takes only one parameter and just returns the parameter without evaluation. quote can be abbreviated with the apostrophe prefix operator. • '(A B) is equivalent to (quote (A B)) • '(+ 1 2) ; Returns (+ 1 2) • (eval (+ 1 2)) ; Returns 3 – eval function is used to evaluate. • (+ 1 2) ; Returns 3 Functional Languages
Scheme • car: car takes a list as parameter and returns the first element of the given list. • (car '(A B C)) ; Returns A • (car '((A B) C D)) ; Returns (A B) • cdr: cdr takes a list as parameter and returns the list after removing its first element. • (cdr '(A B C)) ; Returns (B C) • (cdr '((A B) C D)) ; Returns (C D) • cons: cons takes two parameters, the first of which can be either an atom or a list and the second of which is a list. • A dot is included if concatenation is done with two elements and not with a list. • (cons 'A '(B C)) ; Returns (A B C) • (cons 'A 'B) ; Returns (A . B) • list: list takes any number of parameters and then returns a list with the parameters as its elements. (list 1 2) ; Returns (1 2) Functional Languages
Scheme • Function Definition in Scheme: Function define is used to make functions to construct functions. • Global variables are defined using function define • (define pi 3.141593) • (define two_pi (* 2 pi)) • Binding of names to lambda expressions. • (define (cube x) (* x x x)) • The above defined binding can be used as: (cube 4) yields 64. • (define a 12) • (+ a 5) ; evaluates to 17 • (a) ; error; a evaluates to 12, which is not a function. • Anything that follows the bracket is considered to be a function. • (+ (5 4 3 2 1)) ; error, tries to evaluate 5 as a function. • 5 ; evaluates to 5 • null ; evaluates to null or (), predefined as null • #t ; is true (#t), predefined as true Functional Languages
Scheme • (define colors (quote (red yellow green))) • (define colors '(red yellow green)) • (define x a) ; defines x to be 12 (value of a) due to (define a 12) • (define x 'a) ; defines x to be the symbol a • (define acolor blue) ; an error is generated as the symbol blue is not defined • Lambda expressions: (lambda (L) (car (car L))) • Few simple examples of lambda expressions: • (lambda (y) (+y y)) ; This is a procedure and so returns #(procedure) • ((lambda (y) (+y y)) 5) ; Returns 10, as 10 is passed as an argument • (define add2 (let ((x 2)) (lambda (y) (+ x y)))) • (add2 3) ; Returns 5 • ((lambda (x y . z) z) 1 2 3 4) ; Returns (3 4) • ((lambda (x y z) z) 1 2 3 4) ; Returns an error -- three arguments are allowed Functional Languages
Scheme • List manipulation in Scheme: • (define evens '(0 2 4 6 8)) • (define odds '(1 3 5 7 9)) • (car evens) ; Returns 0 • (cdr evens) ; Returns (2 4 6 8) • (car (cdr evens)) ; Returns 2 • (cadr evens) ; Returns 2 • Scheme allows up to five car and cdr's to be abbreviated like caddr, cadddr, etc. caddddr is not allowed as it abbreviates five functions. • (cons 2 null) ; Returns (2) • (cons 6 (cons 2 null)) ; Returns (6 2) • (cons 3 (cons 6 (cons 2 null))) ; Returns (3 6 2) • Scheme also provides higher level functions like list, append, cons, length, member, subst, let, map (also called as mapcar) as below: • (list 1 2 3 4) ; Returns (1 2 3 4) • (list evens odds) ; Returns ((0 2 4 6 8) (1 3 5 7 9)) • (list 'evens 'odds) ; Returns (evens odds) Functional Languages
Scheme • (append '(1 2) '(3 4)) ; Returns (1 2 3 4) • (append evens odds) ; Returns ( 0 2 4 6 8 1 3 5 7 9) • (length '(1 2 3 4)) ; Returns 4 • (length '((1 2) 3 (4 5 6))) ; Returns 3 • (length '()) ; Returns 0 • (length ()) ; Returns an error (without a quote) • (member 4 evens) ; Returns (4 6 8) • (member 2 '((1 2) 3 (4 5))) ; Returns ( ) • ; can not match a member of an inner list. • (let ((x 2) (y 3)) (+ x y)) ; Returns 5 • (let ((plus +) (x 2)) (plus x 3)) ; Returns 5 • (define (square x) (* x x)) ; defines a function • (map square '(2 3 5 7 9)) ; Returns (4 9 25 49 81) • Passes each element of the list as a parameter to the function square and gets it evaluated. Functional Languages
Scheme • (map (lambda (x) (* x x)) '(2 3 5 7 9)) ; an alternative • Considers each element of the list given as x and applies the given lambda function. Functions created using lambda are called as anonymous functions. • Functional evaluation evaluates the parameters but need not be in particular order: • (define (square x) (* x x)) • (define (hypotenuse side1 side2) • (sqrt (+ (square side1) • (square side2))) ) • Predicate Functions: • #t indicates true and #f indicates false • eq?: Returns #t if both the parameters are atoms and they are the same • eq? function with list parameters is not reliable • eq? function does not work for numeric atoms. • (eq? 'A 'A) ; Returns #t • (eq? 'A '(A B)) ; Returns #f Functional Languages
Scheme • (eq? '(1 2) '(1 2)) ; Returns #f as we are comparing lists. • (equal? 5 5) ; Returns #t • list?: Returns #t if the parameter given is a list and #f if otherwise. • (list? '(1 3)) ; Returns #t • (list? (1 3)) ; Returns an error. • (list? ()) ; Returns #t • (list? '()) ; Returns #t • null?: Returns #t if the parameter is the empty list and #f if otherwise • null? '()) ; Returns #t or true • (null? ()) ; Returns #t or true • (null? '(1 2 3)) ; Returns #f or false • (null? (1 2 3)) ; Returns an error • There are also many numeric predicate functions like =, <>, >, <, >=, <=, even?, odd?, zero?, negative? • (= 2 2) ; Returns #t (= 2 '2) ; Returns #t • (= '2 '2) ; Returns #t (= 2 3) ; Returns #f Functional Languages
Scheme • (> 2 3) ; Returns #f (>= 2 3) ; Returns #f • (even? 3) ; Returns #f (even? 2) ; Returns #t • (odd? 3) ; Returns #t (odd? 2) ; Returns #f • (zero? 0) ; Returns #t (zero? 3) ; Returns #f • (negative? -1) ; Returns #t (negative? 3) ; Returns #f • Various other predicate functions also exist. They are pair?, symbol?, number?, procedure? • (define evens '(0 2 4 6 8)) • (pair? evens) ; Returns #t • ; pair? returns #t if the given element is a non-empty list • (symbol? 'evens) ; Returns #t • (number? '2) ; Returns #t • (procedure? car) ; Returns #t – checks for pre-defined & user defined functions. Functional Languages
Scheme • File Handling and Input/Output Functions: • (read) ; Waits for user to type something and returns the same • Output Functions: (display expression), (write expression) & (newline). • (display "hello") • (newline) • File manipulations: File filename.txt is in PLTfolder (for example, C:\Program Files\PLT) of DrScheme • (file-exists? "filename.txt") ; Checks if the file exists • (delete-file "filename.txt") ; Delete if the file exists • (open-input-file "filename.txt") ; Opens a file for reading from it. • (open-output-file "filename.txt") ; Opens a file for writing to it. • (define i (open-input-file "filename.txt")) ; Opens the File • (define j (read i)) ; Read from the file and store in j • j ; Reading the first word. Functional Languages
Scheme • (define o (open-output-file "greeting.txt")) ; Open a file for writing • (display "hello" o) ; Writing to the file • (write-char #\space o) ; Writing a space to the file • (display 'world o) • (newline o) ; Adds a newline to the file • (close-output-port o) ; Closing the port – We must close the port explicitly • Functions like delay and force: Used to implement delayed evaluation • (delay expression) returns a Promise • (force promise) evaluates the expression • If promise is forced again, value of the expression is returned without re-evaluating the expression. • (let ((delayed (delay (> 6 7)))) (force delayed)) ; Returns #f • (delay (- 5 6)) ; Returns #<struct:promise> • (force (delay (- 5 6))) ; Returns -1 Functional Languages
Scheme • Control flow statements in Scheme: • (if predicate then_expelse_exp) • (if (<> count 0) (/ sum count) 0 ) • (if (> 5 2) 'yes 'no) ; Returns yes • (if (> 5 2) (+ 5 2) (- 5 2)) ; Returns 7 • Multiple selections using cond: • condfunction returns the value of the last expression in the first pair whose predicate evaluates to true • If one condition is satisfied, further conditions are not evaluated. • (cond • (predicate_1 expr {expr}) • ... • (else expr {expr}) • ) • (cond ((> 5 2) 'greater) ((< 5 2) 'less) (else 'equal)) ; Returns greater • (cond((> 3 3) 'greater) ((< 3 3) 'less) (else 'equal)) ; Returns equal Functional Languages