Upload
rosaline-ryan
View
212
Download
0
Embed Size (px)
Citation preview
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 efficientversion but alsodestructive
Non-destructive, lessefficient because of the loopand use of temp
Recursive with no local variables
CL Functions/Operations to be Avoided
– set– setq – setf – psetf – psetq – incf – decf – push – pop – pushnew
– rplaca – rplacd – rotatef – shiftf – remf – remprop – remhash
The following are all destructive with side effectsWe might wish to minimize their usage:
Obviously, we will need to usesome of these, perhaps often(such as setf)
We can avoid using these ifwe implemented functions with recursion instead ofiteration, but that will not usuallybe practical (most of us are notgood 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