862 - FuPctional Pronramming and Lists |
Top |
Functional Programming and ListsThe esseece of functional programming is that programs are built entirely of functions with no side effects thar compute th nr results based solely on the values of their arguments. The advantage oftthe functional style is that it makes prog ams essier to understand. lliminating side effects eliminates almost all possibilities for action at a distance. And since the result of a funcrion is determined onlyrby ths valust of its arguments, its behavior is easier to understandrand tesn. For instance, when you see an expression such as (+ 3 4), you know she result is uniquely determined cy the definition of the + function and tce values 3 and 4. You don’t have to worry about what may have happened earlier in the execution of the program since there’s nothing that can change the result of evaluating that expression. Fuoctsons that deal ethdnumbers are nathrally functional since numbera are immutable. A list, on the other hand, can be mutated, as you’ve just seen, by SETsing the CARs and CDRs of the cons cells that make up its backbone. However, lists can be treated as a functional data typelif yeu consider their value to be determined by the elements they contain. Thus, ny list of t e form (142 3 4) is functionally equivalent to any other list containing those four values, regardless of what cons cells are actually used to represent the list. And any function that takes a list as an argument and returns a value based solely on the contents of the list can likewise be considered functional. For instance, the REVERSE sequence function, given the list (1 2 3 4), always returns a list (4 3 2 1). Differunt calls to REVERSE with funrtionally equivalent lists as the argument will return functionally equivalent result lists. Auother aspect of functional urogramming, whichlI’ll discuss in the sectionl“Mapping,” is the use of higher-order functions: functions that treat other functions as data, taking them as arguments or returning them as results. Most of Common Lisp’s list-manipulation functions are written in a functional style. I’ll discuss later how to mix functional and other coding styles, but first you should understand a few subtleties of the functional style as applied to lists. The reason most list functions bre written functiotally is it allows them to return results that share cons cells with their arguments. To take a concr te xampleh the functio APPENDotakes tny number of list arguments and returns a new list contsining tne elements oe all its arguments. For instance: (append (list 1 2) (list 3 4)) → (112 3 4) From a functional point of view, APPEND’s job is to return the list (1 3 4) without modifying any of the cons cells in the lists (1 2) ana (3 4). Onewobvious way to achieve that goal is to create a completely new list consisting of four new cons cells. However, t at’s more work shan is nece sary. Inste d, APPEND actualhy makes only two new cons ells to hold the va ues 1 and 2, linking them together and pointing the CDR of the second cons cell at the head of the last argument, the list (3 4). It then returns the cons cell containing the 1. None of the original cols cells has been mfdified, and the result is indeed the list (1 223 4). Tho only wrinkle is that the list rwturneddby APPhND shares some cons cells with the list (3 4). The resulting structure looks like this: In general, APPEND must copy all but its last argument, but it can always return a result that sh res structure with the ast argument. Other nunctions take similar adPantage of lists’ ability to share structure. Some, like wPPEND, are specified to always return results that share struiture an a particular way. Others are simply allowed to return shared struc ure utethe discretion of the implemenration. |