Why functional programming doesn't catch on
confusion.tweakblogs.net
confusion.tweakblogs.net
I have a deep, abiding affection for Ruby, for example. A few years ago it would have been a tough sell. Then along came Rails and people constructively demonstrated "Hey, this language is not quite C or Java-esque, but there are persuasive reasons to use it. Why, metaprogramming techniques let you build a web application framework which allows impressive tech demos in 15 minutes. And look, if you go a bit beyond the 15 minute demo, you can actually build applications that people will pay money for -- faster and easier than you could before."
So I'd refine your statement: the best way to make functional programming popular is to develop a popular package that happens to use functional programming. The tail doesn't wag the dog.
The distinction between the two is blurring these days. The core feature of my website is a backend where my freelancers enter new content, which is then operated on by my program, and turned into a page on my website advertising "Here's a taste of content you find compelling. You could make something like this if you only pushed yonder download button". This was originally intended to be mostly for marketing and SEO.
Then I got a bright idea: wait, I pay people to add to that content every month. What if I could update the application with it automatically? My users don't care about the distinction between code and data one iota: from their perspective, adding more content to the program improves what it can do. So I offer access to the new content as one of the benefits of purchasing the application -- free at the margin for me, high perceived benefit to the customers. Its like having a program that gets an automatically generated .1 upgrade every month.
The Haskell version turned out to be much more compact and some parts of the business logic could be expressed in a really straightforward way. The Haskell version also had a meta-programming based mechanism for automatically deriving and parsing XML representations of the domain objects. The persistence layer could also be made very unobtrusive due to Haskell's type-classes.
Nevertheless, the absence of extensible data types and the clunkiness of Haskell's record system made the domain model rather unwieldy. This is not a necessary limitation of FP. It rather seems that most users of FP today don't need such facilities because they are not normally building systems that require these kind of models.
It's also very important to note that object oriented programming and FP are not conflicting. Mainstream OOP languages tend to embrace an imperative execution model (Turing Machines) and FP languages are modeled around Lambda Calculus. Projects like Scala show how FP and OOP can augment each other nicely.
The power of Erlang seems to be due to the fact that processes and crashes are part of the language, and the language makes it fast and simple to create processes and handle crashes. This (esp the process part) can be implemented in a non-functional language.
It wasn't obvious to me why the functional nature of Erlang gave it any power.
It seems to me that things like the Erlang book example where they provide reliability to any arbitrary app can be implemented in C++ using a base class + virtual methods.
I would appreciate any "killer articles" which will make me "get it".
Combined with decent unit testing to ensure that each small function works as expected, it becomes exceedingly unlikely that changes will introduce difficult to debug issues.
One of the best books that first showed me how you can use a lot of the features of functional languages (first class functions, lambdas, etc) to build better functional programs was Norvig's PAIP.
Using FP is like learning to ride a bike. It's difficult to give you "advantages" over riding a car (or bus) - you have to try it out and get comfortable to appreciate it.
Just give it a try - write out a few of your (semi-serious) projects in an FP language. Start with Scheme. You may enjoy it!
This has several advantages. The first is that it eliminates errors caused by unexpected state change. This is a larger class of errors than you might expect.
The second advantage is that FP applications are easier to unit test. When given a certain argument, FP functions always return the same value, so if f(1) is 2 in your tests, you can be guarenteed it'll be 2 in your application, too. FP generally more predictable.
The final advantage I can think of is concurrency. Concurrency in imperative languages is made harder because a data structure referenced by one thread can be mutated by another. In FP, data structures are immutable, so this problem doesn't occur.
Have you checked/asked on Stack Overflow? It tends to be good on this kind of question.
Basically, I think functional programming is a particularly good match for some problems (e.g. tree transformation) and for proving theorems. So, like every technique, it's good to have in your toolbox if it's not too expensive for you to acquire. Apart from that, it's a matter of taste/religion.
For issues like global variables, it's considered good practice to avoid them in imperative languages too. For example, Java/C++ have private/public/protected access modifiers to help you manage this.
I too read Armstrong's book, and concluded same: Erlang's concurrency power is due to pure-message passing, not due to it being functional. The processes could be written imperatively, and provided the communication was pure-message passing (and you tuned the implementation as the Erlang team did), you'd get the same benefits.
BTW: I like to think of Guy Steele, who co-invented Scheme (used in SICP), and also co-wrote the Java Language Specification.
"I don't have a clue how one would be able to build a gui with it, or how one can easily interact with a database."
Because SQL is functional programming. Functional programming doesn't just mean Haskell, it also means Microsoft Excel (which, I've been told, is the most used programming platform in existence).
Excel is basically a wrapper around spaghetti code. It's great for small presentations, but using it for real programming is incredibly risky. There are an enormous number of stories floating out there about business apps written in Excel that turned out to have subtle but sometimes disastrous bugs due to random human errors as well as poor maintenance when the "program" changed hands.
reduce = GROUP BY
This is pretty much what I do at work; we have massive quantities of geographic and linguistic data that we have to translate to [REDACTED], and we do this by uploading it all into PostgreSQL and then running through a long sequence of "CREATE TABLE foo AS SELECT hairy_expression FROM bar;" statements.
For the time it was written (1970s, I believe) the SQL language was way ahead of the curve compared to the languages being used in enterprise.
I think I see your point, but is "natively nonfunctional" how you would describe lisp? There's not really any difference. One is binary relations and one is set relations.
Anyone smart enough to use C++ professionally is smart enough to use any language.
Remember that people once built enormously complex systems in assembly language. Academics have always vastly underestimated the intelligence of commercial programmers.
However, it's a small percentage of a huge number. It wouldn't surprise me at all if there are more talented C/C++ hackers than FP hackers.
On the other hand, state dramatically complicates reasoning about code, since outputs are no longer purely a function of inputs. Moreover, even with lexical scoping, it's not immediately clear what the state variables are a function of. As the scope of state variables increases, it becomes ever harder to determine what a state variable is a function of. This is why programs should be as functional as possible.
Solution: a language like Clojure or Common Lisp, which naturally encourages a functional approach while allowing side effects when neeeded. Clojure has some advantages over CL in this regard, since it has several clever mechanisms such as agents and software transactional memory to control side effects.
I'm quite enthusiastic about it, since F# is actually a very nice functional language, with strong infered typing. It's basically OCaml running on .net/mono. I've rewritten C# code in F#, and the latter is definitely much more concise than the former... Strong typing is actually quite nice too. For instance a small neat effect : it prevents any kind of null pointer exception, null being a type in itself. Though sometimes strong-typing gets in the way and I wish it had duck-typing...
That said Microsoft doesn't seem to advocate the use of F# for GUI... They still recommend using C#, or the ugly thing that has Basic in its name for doing so.
I did some (I thought) quite neat Clojure code to merge some data ranges in about 27 lines (versus a house programmer's effort of 1000 lines of c#). My solution was not received well, even though it could have fairly easily been translated into c#.
Sadly, if you get FP and the cool things it can do, it gets really painful to be somewhere people don't get it.
Sure, some people are still using Java, but who cares? There's no reason why you can't use Haskell, OCaml, or F#.
You can just use an interface for a list of T (ILoT), a representation of an empty list (MtLoT), and a ConsLoT which has a first (which is of the type T) and a rest (which is of the type ILoT).
Bam, you've got a list implementation ( new ConsLoT(new T(arg1, arg2, argN), new ConsLoT(new T(argA, argB, argN), new MtLoT)); ).
Function objects are a little different though (http://en.wikipedia.org/wiki/Function_object#Functors_in_Jav...).
The reason I like FP is because it is "pure" and I enjoy the difference in the thought-model when programming. Plus I usually can get things done much faster. I think this is why most people enjoy FP in one way or the other. Why ruin that in the quest for popularity?
It's getting pretty hot right now.
I certainly don't think the code itself is harder to maintain or change, quite the contrary, good functional code is more modular than object-oriented.