Why Functional Programming

A discussion continued from ComputerScience...

"... You are absolutely correct that I think functional programming (FP) is not fit for the real world as it excludes 1/2, the data half, from it's definition. In the end, they will tell you to store your state in a RDBMS if you need to. ... Functional programmers think of variables as evil so they juggle the variables on the stack as passed parameters and give up to the database when that doesn't work. Languages that include both data and programs can execute functions just as well as functional programming does and also look after the variables. The argument that FP, without real variables fixes concurrency problems might be true but there are other techniques that also solve concurrency problems while not giving up the data part that is intrinsically what computers are all about. FP is mostly used by academics that enjoy a Math style syntax. It doesn't surprise me that the vast majority of programmers have never even bothered to look at it. I look at FP as a specialized "Domain Specific Language DSL" that has some useful purpose to Math professors who don't want to learn how to really program! ..." -- DavidClarkd

Your assessment of FunctionalProgramming shows some typical misunderstandings and prejudices. Before hastily dismissing it, try some practical experimenting with Haskell, F# or Lisp. It can be an enlightening experience, helpful for improving your code and (perhaps especially) the way you think about code, even if you don't use it for "real world" projects.

Like all good programmers, I am always open to learn something new but I am curious, what in my post makes you think I either don't have extensive experience, haven't programmed in enough languages or know little about functional programming languages? I would give you a little friendly advice and ask you to study FP yourself. If you care to know what kind of experience I have, just follow the link to my web site from here. I have known about Lisp programming since 1978, can you say the same? That was 3 years after I bought and put together my first micro computer and just 1 year before I wrote a 50,000 line word processing program in Z80 assembler. -- dc

[One thing that comes to mind is "functional programming (FP) is not fit for the real world as it excludes 1/2, the data half, from it's definition". This is simply a false statement. Functional languages do not ignore the data half, and it's such an obvious error that it makes it extremely unlikely you have any significant experience with them.]

I have read the small list of features on this wiki that supposedly define FP but most of these features are also used in other languages and are not specific to FP. The list includes FirstClass functions, HigherOrderFunctions, LexicalClosures?, PatternMatching, SingleAssignment, LazyEvaluation, GarbageCollection, TypeInference, TailCallOptimization, ListComprehensions? and Monadic effects [OnMonads]. Except for the monads which are just a place to encapsulate "effectfull" code, all these features exist in non FP languages and most are in my non-FP language as well. What differentiates FP from other languages is the fixation on variables that can't vary! I have never written a program that didn't contain "immutable" objects but we always just called them a "constant". I have only rarely ever written a program without "variables" (named objects whose state can change) and I can't conceive of writing anything complex without them and constants, of course. Just creating a huge number of 3 line functions to avoid a simple variable definition isn't progress! I just read yesterday that "immutable named values" are natural in Math which I don't believe should matter in CS! Clojure is a FP version of Lisp (according to it's inventor) and he is one of the few language designers (excluding myself) that publishes the "Why" of their design decisions. -- dc

"There is another way, and that is to separate identity and state (once again, indirection saves the day in programming). We need to move away from a notion of state as "the content of this memory block" to one of "the value currently associated with this identity". Thus an identity can be in different states at different times, but the state itself doesn't change. In Clojure's model, value calculation is purely functional. Values never change. New values are functions of old, not mutations." This quote was taken from the Clojure web site and was written by the author of that language. I have never read any technical description about FP that didn't say "immutable data and first class functions" which is why I would say those 2 features "define" FP. Why not actually make an argument instead of just "name calling"? -- dc

The "fixation on variables that don't vary" and focus on "immutable data" has a sound basis: Much complexity and difficulty in programming comes from managing state, to the point that we consider it good practice to avoid unnecessary global variables, define read-only operators where possible, use immutable values wherever possible, or employ the features of functional programming languages -- all to avoid the pitfalls of stateful programming. Of course, many OO proponents take the opposite approach and encourage creation of little state machines everywhere, but they too grapple with state by dividing it into manageable chunks (i.e., instances) defined by explicit boundaries (i.e., classes). Pragmatically, state is a necessary thing. We can't escape it, even in functional programming languages. However we manage it, manage it we must. So, we strive to make state management as painless as possible. In typical imperative programming languages, among whatever other practices we employ to manage state, we know that state changes internally occur at one and only one point -- assignment. If we can reduce or eliminate assignment -- whether with functional programming or various techniques in imperative programming -- we can reduce state management, and if we can reduce state management, we can reduce complexity, and if we can reduce complexity, we gain reliability and maintainability. (Note: this text is partially extracted from a post of mine on another forum.)

Managing state isn't easy, I will grant you, but it is almost always the whole point of programming. -- dc

Managing state is no more the point of programming than drilling is the point of carpentry. Nobody "needs" drilling; what they need are holes. A drill is just a tool to make a hole. Likewise, nobody "needs" state; what they need are their requirements met. The goal of programming is to define a mapping from input (keyboard, mouse, storage, audio input, whatever) to output (screen, speakers, storage, whatever) that meets a set of requirements. Managing state in an imperative programming language is just one way to do it. Managing functions in a functional programming language is another way to do it. Whether one is superior to the other, and whether this superiority is general or specific to particular requirements, or even exists at all, remains to be determined.

Your "mapping of input to output" is the function of a calculator which most programs are not. Data has value even when the computer is shut off. Non FP can use all functional techniques and more. FP is but a subset of the set of useful programming tools. -- dc

I'm not deprecating the value of data. A misconception about FunctionalProgramming is that it tries to eliminate data. It does not! Data is fundamental and vital. FunctionalProgramming tries to reduce or eliminate transient state as it is typically used inside of programs to define mechanisms that manipulate, manage, or present data. Mapping of input to output can be illustrated by a calculator, but a more appropriate example is a spreadsheet. Spreadsheets can serve as good examples of practical, day-to-day FunctionalProgramming; a spreadsheet's formulae and cell references form a functional program that maps input (cell values) to output (also cell values). A general-purpose FunctionalProgramming language embodies precisely the same concept, except instead of I/O being limited to cell values, it works with the standard I/O mechanisms of any computer along with, for example, persistent data storage and/or data management like databases and DBMSs.

Global variables are bad and should be avoided. Agreed. -- dc

We already define "read only" variables and call them constants. -- dc

Yes, though I referred to "read only" operators, i.e., those without side-effects. Side-effects complicate programming.

I don't understand the concept of a "read only operator"? Operators, to me, mean programs. Are you talking about a program that you can't change? We have to use a similar language if we want to communicate. I talk the same computer language you learned at University so ... -- dc

"Operator" is the term that encompasses both functions and procedures. A read-only operator does not have side-effects.

OO programming is all about "side-effects" as the functions are supposed to change the data of the object. Calling them "side effects" when they are the "purpose" of the function is typical of FP. Saying a variable is "immutable" would be an oxymoron to any normal person. -- dc

If you're thinking in OO terms, then "side-effects" are a goal of certain functions. If you're thinking in FP terms, then "side effects" are most certainly not a goal, but that's because FP is a fundamentally different approach to programming, just as going from procedural programming to OO programming is a fundamentally different approach to programming. I don't think anyone has claimed that variables (at least, in the usual sense) are immutable. That would be contradictory. There are certainly constants in some languages, and re-assigning a variable in some functional languages is not the same as re-assigning a variable in an imperative language. You may be thinking of immutable values (see ValueObject and ValueObjectsShouldBeImmutable) which is something else entirely.

Being "fundamentally different" isn't an argument in FP's favour. APL was also "different" but can't be compared as an alternative to OO, can it? Please name a language that doesn't have "constants"? Even "toy" computer languages have "constants". If you read my quote from the author of Clojure, you would find I am absolutely saying that FP is fundamentally about immutable values which are exactly the same as a named constant in any other language. Just read the quote. Better yet, go look up the language author's comments on the clojure.org web site and read it yourself. -- dc

Being "fundamentally different" wasn't an argument in OO's favour, either, but that didn't stop it and I see no reason why a modern implementation of APL couldn't be an alternative to OO. I agree that FP is fundamentally about immutable values. Values are not variables.

JavaScript doesn't have constants.

You state "use immutable value whenever possible" which I know it the main thesis of FP but where is your evidence to support this conclusion. Stating your conclusion doesn't make it true. -- dc

If we take as given that much complexity and difficulty in programming comes from managing state, then using immutable values reduces state management (by definition), and hence complexity and difficulty can be reduced.

That would only be true if variables are used when constants would work. That is not my experience. I know how to use both! Your complexity supposition is not convincing. -- dc

Convincing or not, it's true that state management is difficult, so reducing state -- in general -- reduces complexity. Whilst replacing variables with constants is part of that, it's not limited to it.

Creating functions increases complexity. Additional programming of any kind increases complexity. My argument is that FP increases functional complexity even if it decreased complexity by reducing state which I am not convinced it does. The biggest problem I have in programming is containing "effects" so that the space I need to search when something goes wrong is small. If there is clear responsibility for each "object" and those functions can be contained to only that "object", then a huge group of problems will be solved. This exactly why OO encapsulates state and the functions that work on them. Denying the fact that state is required or juggling it in function parameters is worse not better. -- dc

How is it worse?

Problems normally require both data and functions to coordinate what they are trying to do. It takes much longer to track problems if 1) you don't know where to look for the problem 2) changes you might make to that function break functionality used elsewhere. -- dc

Are you referring to the syntactic coupling of functions and variables, in classes, that is common to a number of OO languages?

Yes!

That's merely a syntactic characteristic, and a rather limited one at that. It tends to imply SingleDispatch, when MultipleDispatch is superior. There are other ways of following a chain of dependencies.

I am glad to hear that (at least one) FP aficionado admits that state is "a necessary thing". Encapsulation done right, not only shows whose responsible for the data but also keeps the functions responsible for that data close so they can be fixed with the data when necessary. -- dc

Yes, that is reasonable. I'm not convinced it's any better or worse than FP equivalents, just different.

I do understand that most FP languages have a mechanism to group sets of functions which would at least "encapsulate" a group of functions at some level. -- dc

I get temporary data all the time from it's "home" object and manipulate it locally. Without assignment, I would have to have pointers to the original which causes way more problems. One of the biggest differences between Java and C are the pointers in C and lack thereof in Java. -- dc

Java references are equivalent to pointers. I'm not sure what that has to do with creating local copies, and certainly FP lets you create local copies of data where appropriate.

I don't believe that indexes into an array are equivalent to a memory pointer or that a key to a database record is equivalent either, even though all 3 give a location for the data. In C you can set a pointer to anything, including to all kinds of locations you have no right to be. Are you disputing this? Aren't local copies assignment which you say is bad? -- dc

Assignment, and even local copies, are not necessarily bad. FP seeks to reduce or eliminate unnecessary state management; it doesn't seek to make programming difficult. It seeks, in fact, to take away as many difficult parts as possible (once you've gotten over the learning hurdle, of course, but that's true of any new language or paradigm) so you can concentrate on the important aspects of solving the problem. In short, it seeks to remove the usual imperative programming stateful scaffolding -- of which there is much, and we spend a lot of time on it -- so that you can focus on implementing the requirements. Regarding pointers et al., I made no comments about array indexes and what you can do with pointers in C. I noted only that Java references are equivalent to C pointers, i.e., a reference in Java "points to" an object such that multiple references can refer to the same object, same as a pointer. The fact that C also lets you perform pointer arithmetic, etc., only means that C pointers are not equivalent to Java references.

You are just using word games for what we both know to be true.

It is poor debating technique to base rhetorical arguments on what you assume to be the beliefs of your correspondent. I'm not clear what it is that you believe I "know to be true", and by extension, what it is that I wrote that you disagree with.

I have programmed in C for decades as I am sure you also have. There is no point debating pointers when we both know exactly how they work in C and Java. -- dc

Indeed, though I'm still not clear whether you're agreeing with me or disagreeing with me. If it's the latter, I'm not sure what we're disagreeing about.

We agree state is necessary so I vote for more and better facilities to realize correct and useful state. Just trying to avoid state by increasing function use just adds to complexity rather than the opposite. -- dc

I agree. However, I believe FP is one approach to finding "more and better facilities to realize correct and useful state". FP doesn't avoid it, it tries to abstract it and/or encapsulate it so we don't have to deal with it -- it's complex, remember -- any more than necessary. A lot of programming involves dealing with state we don't have to deal with. Iteration over a collection is a common example: why should we have to maintain an index when the program can do it for us? Or, why should we have to iterate explicitly and call a function with each value, when we should simply be able to apply the function to all values?

Encapsulating state is the definition of OO isn't it? My language iterates automatically over all the objects defined in my system. My system automatically maintains indexes that are linked to Lists and Tables without any code at all. My system can easily handle the MAP/REDUCE pattern in a much easier manner that making it look as if a function must be called for each row or element of a collection. Actually, any decent FP compiler would create a loop and inline the function to execute MAP/REDUCE. In my language, you can have a macro do that for you or you can just specify exactly that. -- dc

Without knowing your language, it sounds like you are incorporating facilities often found in functional programming languages. That sounds good. It matters not whether it's implemented with macros or something else.

FP wasn't the creator of most of the features you attribute to it. First class functions were first put into Lisp in the 1950's. I created an Xbase language/data manager in the 1980's and some of the techniques came from there. I personally don't care where "good ideas" come from, so long as the are, well, good! I have an If and While statement and a FOR/NEXT loop. These came from Fortran and Basic. All languages borrow from others. My system has a modified form of the "actor" model at it's macro level, with all variables being "objects". Although my system is basically OO, you can use SQL directly in the language using compile time macros. To some people, it would be something like a memory/disk based RDBMS where you get to define data and program from the inside while the whole system continues to run. -- dc

FP is not an individual, so I doubt it was the creator of anything. FP is defined by a collection of diverse features, but most definitions share the common characteristics of deprecating stateful programming and (typically) supporting first-class and higher-order functions.

Excuse me but I was referring to languages instead of implementations. My point was FP didn't invent much. I would agree with your succinct definition of FP, however. -- dc

You are excused. FP didn't invent anything, and I don't think anyone claimed it did. "FP" is a post-hoc categorisation of languages; it didn't exist before the languages that we now consider to be FP, like Lisp. It was identified after there was a category of languages that shared the characteristics I mentioned.

State is correct or not, based on the correctness of the functions that change it. State is maintained by functions. -- dc

Increasing reliance on functions to try to minimize state, just increases complexity, reduces reliability and makes maintenance more difficult. -- dc

How so?

I have looked at a few thousand lines of FP code and I have noticed that the functions are very small and numerous. (It is possible that isn't true in the general case but I am sure you can correct me if I am wrong.) I believe that complexity increases with the number of "objects", number of functions and the amount of interaction between those "objects". Lines of code doesn't increase complexity and sometimes, less code can be much more complicated. -- dc

Small and numerous functions -- as compared to large and few functions -- are easier to test individually, easier to understand individually, easier to debug individually, and easier to re-use and compose into more complex mechanisms.

The programming world isn't so simple. I have many quite small functions that do specific jobs and are used quite universally, I have other functions that work as a group on specific data structures and I have others that perform somewhat complex tasks that are only called from a single location. I am sure I could create my other "groups" of functions. Some functions can't be tested individually! Any general purpose language can accommodate any of these kinds of functions including the simple ones you describe. -- dc

Some functions can't be tested individually? Have you not been doing TestDrivenDevelopment?

I'm not saying that all functions should necessarily be small. However, more small functions are preferable -- for the reasons I stated above -- to a few large ones.

The functional or calculator paradigm is not always the worst approach. A good object oriented language would include the ability to have "first class functions", allow "pure functions" without side effects, objects without data and also the ability to track changes to variables over time. The point is that a full computer language must be able to accomplish many things without having whole classes of capabilities thrown away to uphold principles that sound more like a religion. I am a big fan of "domain specific languages" DSL. APL was a favorite language of mine in the 1970's and I think FP could fill much the niche today but FP is not an alternative to OO. -- dc

What's a "calculator paradigm"?

Input, calculate, display result, stop. No state, just functional manipulations of input to output without any side effects. Even a word processor and a spreadsheet have significant state! -- dc

Indeed, but a word processor document is data. A spreadsheet is data. Data is fundamentally important. As I noted above, FP seeks to eliminate unnecessary transient state from programs. It does not seek to eliminate data; indeed, it's intended to make working with data easier and more reliable. As I also noted above, spreadsheets are an excellent example of FunctionalProgramming at work. In fact, given that (as of 2002) roughly 50,000,000 people could write spreadsheets, but only 2,000,000 or so could write "classical" imperative programs, it would appear functional programming is considerably more used than imperative programming. (See http://web.cecs.pdx.edu/~black/S3S/PeytonJones.ppt)

What language is designed to create unnecessary state? I only create "state" that I think is necessary! You consider a person that enters numbers in a spreadsheet to be equivalent to a programmer? You either 1) know nothing about programming or 2) are just trying to tell a joke. Either way, no further response to that comment is justified. -- dc

Many languages necessitate unnecessary state. A trivial example is this:

 for (int i=0; i<v.length; i++)
   fn(v[i]);
Which could be this:
   apply(fn, v);
The state represented by 'i' is unnecessary.

Having an 'i' variable or not is trivial and in most modern languages, you can iterate over any collection without any index at all. Take Ruby for example.

Indeed, it is trivial, which is why I (meant to; typo, oops) wrote "A trivial example is this:". It's a simplistic illustration of the concept. Imagine endeavouring to eliminate all such 'i's, and all such similar use of stateful variables, wherever possible without loss of power or expressiveness. That, in short, is what FP is trying to achieve.

I never have more than a few iterators in any single function in C and because I always just call them i, j, and k, they aren't a source of errors. As I said, my language, as well as most modern languages can iterate over a collection without any variable at all. Even PHP! -- dc

Fair enough, but my iterator variable example was intended to be a conceptual illustration, not a core issue. Stateless iterators are a good starting point, but they are only a starting point.

The main concept of FP is to describe "what" you want done rather than "how" you want it done.

Yes, functional languages are often considered to be declarative as well.

As for knowing nothing about programming, it is true that I still have so much to learn, as I've only been doing this for 36 years or so. Despite that, I am the lead developer of the RelProject, which internally uses a highly functional-style core written in Java.

I have similar time in our field and I am the designer of a new language written in 50,000 plus lines of C using a highly OO style. I limit my globals to a only a few thread specific variables.

It's true that someone who just enters numbers into a spreadsheet is not a programmer. However, someone who creates a spreadsheet model, with formulae, is doing FunctionalProgramming.

The main concept of FP is to describe "what" you want done rather than "how" the computer will do it.

To a certain degree, but I think you may be confusing "functional" with "declarative". Functional languages tend to be declarative, but they are not necessarily declarative. Lisp is functional, but not declarative in the usual sense.

Haskell documentation says that the purpose of FP is to describe "what" you want done rather than "how" the computer will do it.

Haskell documentation says that SQL is said to be a "nearly-functional language".

I would call SQL a "domain specific language" DSL as it's purpose is specific to manipulating tables, stored in databases. It is "declarative" rather than "imperative", however, much effort involved in creating a RDBMS is in converting that declaration into an imperative program that can actually accomplish the task.

I understand how, given a specific domain, that a description of the "what" can be translated into the ordered set of instructions that actually do the work, and I have included many features in my language design to facilitate DSL translation BUT how is it possible in the general case?

If you said MAP/REDUCE is an example that can be included in "general" languages, I would say that is a trivial example.

MAP/REDUCE is just a function passed to another function along with a collection. The passed function is applied to each element of the collection. In pseudo code it would look something like this.

 FOR EACH list      // this would loop over all elements of "list" and execute the "some code"
   { some code }
 NEXT
You could replace the code with a function call if you wished. By the way, the above code is actually from my language. In my language, you can not only pass a function as a parameter or return it as a function result, you also can have access to that functions source code, you can change it if you want and then run it all at execution time from the same function.

First class functions don't define FP!

In a general purpose language, somewhere you must actually have code that the computer can actually execute. If you look at FP code, you will not find a "declarative" list like you do with SQL. No general purpose language could! You will find many nested functions that use syntax as close to Math as possible (lambdas), that make a big deal out of variables. Yes, I mean variables that can be changed rather than named constants that some call "immunable values"! I have created many "pure" functions in non-FP languages but "correct" functions are actually much better.

In my language, I have 2 very different kinds of "objects". One kind (Server Object SO) are globally exposed but can only be accessed with "real messages" and flexible interfaces that can enforce multiple kinds of security. Within this kind of "object", you can define "objects" that are derived from "classes", encapsulate data and have there own functions. Internal functions always expose all functions and data but are 100% enclosed inside the outside "objects". You get both kinds of object without all the complications of public/private etc. Why would you hide data from yourself? No global data can be specified.

Benefits of my design:

This is just a small example of what my language can do. Checkout my website for more information. -- DavidClarkd

This appears to have changed from being about FunctionalProgramming in general to being a pitch for your language in particular. You may wish to create a separate page for it.

I have created a page MathPurityUseful where I have explained some of my ideas and if you respond, we could explore our differing views of CS. I quickly looked at RelProject and I am quite interested in going over it in more detail. -- dc

I have created a page at MaxOopsRelational about my language but I am only using my language design here to show that FP doesn't have a monopoly on many good features like "automatic memory management" etc.

I don't think anyone claimed that FP has a monopoly on good features. It doesn't.


CategoryFunctionalProgramming


EditText of this page (last edited October 17, 2013) or FindPage with title or text search