60 likes | 88 Vues
Understand the principles of functional programming, compare functions vs. procedures, explore functional design tips, and avoid destructive operations. Learn the advantages of functional programming and consideration when implementing it.
E N D
Functional Programming • Here we briefly look at what functional programming is and why we want to study it • a function, in the mathematical sense, is a set of operations that perform some computation on the parameter(s) passed, and return a value • a function, in a programming language, is a set of code whose purpose is to compute based on the parameter(s) and return a value • Functions are often used to promote modularity • break down program tasks into small, roughly independent pieces • this promotes structured programming in terms of design • this also aids debugging, coding and maintenance • However, the function, as we see them in programming languages, does not necessarily reflect a mathematical function
Why Not? • Functions may act more like procedures • a procedure is another unit of modularity • the idea behind a procedure is to accomplish one or more related activities • the activities should make up some logical goal of the program but may not necessarily be based on producing a single result • procedures may return 0 items or multiple items unlike functions • In languages like C, there are no procedures, so functions must take on multiple roles • mathematical types of functions • functions that act as procedures • Such functions can produce side effects • mathematical functions do not produce side effects
Functional Design • Functions should • be concise • accomplish only a single task or goal • return one item • in CL, if we need to return multiple values, we can wrap them into a list (or other structure) • there is also a way to have CL functions return multiple values although that is generally discouraged • have no side effects • because the assignment operations are done by function calls, the function calls must produce side effects in such circumstances, but in general, YOUR code should not produce side effects • destructive operations are available and are often much more efficient than their non-destructive counterparts, but should not be used haphazardly or just because they are more efficient • use parameter passing for communication • rather than global variables • exploit recursion when possible • this simplifies the body of a function and requires fewer or no local variables
Comparison Example (defun bad-reverse (lis) (let* ((size (length lis)) (limit (truncate (/ size 2))) temp) (dotimes (i limit) (setf temp (nth i lis)) (setf (nth i lis) (nth (- size i 1) lis)) (setf (nth (- size i 1) lis) temp)) lis)) (defun better-reverse (lis) (let ((temp nil) (size (length lis))) (dotimes (i size) (setf temp (append temp (list (nth (- size i 1) lis))))) temp)) (defun best-reverse (lis) (if (null lis) nil (cons (car (last lis)) (best-reverse (butlast lis))))) The most efficient version but also destructive Non-destructive, less efficient because of the loop and use of temp Recursive with no local variables
set setq setf psetf psetq incf decf push pop pushnew rplaca rplacd rotatef shiftf remf remprop remhash CL Functions/Operations to be Avoided The following are all destructive with side effects We might wish to minimize their usage: Obviously, we will need to use some of these, perhaps often (such as setf) We can avoid using these if we implemented functions with recursion instead of iteration, but that will not usually be practical (most of us are not good at recursion) Note that this does not include the n-destructive functions like nconc and nreverse since there are non-destructive counterparts, these should be avoided
Advantages? of Functional Programming • Easier to design • everything is a concise module • Easier to debug • if all functions are concise, they contain little code leading to easier debugging and less need to insert break statements to find where things are going wrong • Can lead to more efficient programs • debatable • Can lead to more efficient use of the programmer’s time • but if you aren’t good at recursion, is this going to be true? • Leads to aesthetically cleaner code • yet can be more awkward to maintain • Functional languages are often interpreted • this allows quick implementation and testing • this allows for incremental design and implementation of code