Here we discuss the advantages (or lack thereof) of FunctionalProgramming.
Please excuse this very basic question, but what are the fundamental advantages FunctionalProgramming is claiming? Being more high-level? Easier to test? ...? -- FalkBruegmann
Practical advantages:
- Most functional languages provide a nice, protected environment, somewhat like JavaLanguage. It's good to be able to catch exceptions instead of having CoreDumps in stability-critical applications.
- FP encourages safe ways of programming. I've never seen an OffByOne mistake in a functional program, for example... I've seen one. Adding two lengths to get an index but one of them was zero-indexed. Easy to discover though. -- AnonymousDonor
- Functional programs tend to be much more terse than their ImperativeLanguage counterparts. Often this leads to enhanced programmer productivity.
- FP encourages quick prototyping. As such, I think it is the best software design paradigm for ExtremeProgrammers... but what do I know.
- FP is modular in the dimension of functionality, where ObjectOrientedProgramming is modular in the dimension of different components.
- Generic routines (also provided by CeePlusPlus) with easy syntax. ParametricPolymorphism
- The ability to have your cake and eat it. Imagine you have a complex OO system processing messages - every component might make state changes depending on the message and then forward the message to some objects it has links to. Wouldn't it be just too cool to be able to easily roll back every change if some object deep in the call hierarchy decided the message is flawed? How about having a history of different states?
- Many housekeeping tasks made for you: deconstructing data structures (PatternMatching), storing variable bindings (LexicalScope with closures), strong typing (TypeInference), GarbageCollection, storage allocation, whether to use boxed (pointer-to-value) or unboxed (value directly) representation...
- Safe multithreading! Immutable data structures are not subject to data race conditions, and consequently don't have to be protected by locks. If you are always allocating new objects, rather than destructively manipulating existing ones, the locking can be hidden in the allocation and GarbageCollection system.
The most basic claim of
FunctionalProgramming is that
ReferentialTransparency is a
GoodThing. (i.e., "no side effects") Programming without
SideEffects has the following advantages (I will use the generic term "subprogram" instead of function, routine, method, what have you):
- Easier to reason about subprograms. A subprogram's function is completely described by what goes in and what comes out.
- Safe reuse of subprograms. Since subprograms do not alter some database behind your back, you can call them as many times as you want, even in different threads, etc., without having to worry about the state of the program.
- Easier testing. Subprograms are like mathematical functions. If they produce the right answer today, they'll produce the right answer tomorrow.
So based on these observations, we want to limit
SideEffects as much as possible. You can do this in any programming language, but if you try it in
CeeLanguage, it becomes impractical very fast. As it turns out, you will probably at least need the following:
- GarbageCollection: FP data structures are typically lists, trees, etc. rather than arrays, and free() is very non-side-effect-free
- TailCallOptimization: iteration is no good when programming functional, so it's all recursion, and you don't want it to be too inefficient to be practical
- LexicalClosures: not sure they are needed, but life without them s*cks anyway.
Given all these, FP becomes practical. However, once you have denounced the
evilness of
SideEffects, some other things become practical, most noticeably:
- LazyEvaluation: this is what HaskellLanguage does. It means that values are only computed when, and if, they are actually needed, instead of when they are passed to some function.
- Partial Evaluation. Since FP subprograms do not emit communications, you can execute them at compile-time with fixed-parameter inputs and inject the final fixed outputs (which may be partially-evaluated functions or final values) into the program. This can operate both as an optimization and as a basis for metaprogramming (with logic far more complex than the C++ '#if defined(X)').
- Memoization: Since the program-state and emitted communications are unaffected whether you execute an FP subprogram just once instead of twice, you can get by with just executing it once instead of two or more times... e.g. by memoizing answers. The advantage is, of course, limited to expensive computations with the tendency to repeat themselves... but where the compiler can identify those (or the programmer can cue the compiler) it makes a very simple and very powerful optimization.
- AutomaticParallelization?: the eternal promise of FP (that one day we might remove the VonNeumannBottleneck). Not yet realised in practice.
The latter is promised by Data Parallel Haskell (
http://www.haskell.org/haskellwiki/Data_Parallel_Haskell )
which will hopefully be usable soon.
Bravo, that's a very nice answer to the question.
It's a very nice answer to some question.
All the preceding is good stuff, but explains mainly why FP is pleasant. It's an advantage for programmers to work in a pleasant language, of course. But consider this: Ericsson have used a home-grown FPL, ErlangLanguage to build big telecom systems. Apparently they measured improvements in productivity between 9 and 25 times greater. Give that some thought.
Greater compared to what? Hand-hacking in AssemblyLanguage? Coding parallel systems in CeeLanguage?
Greater than whatever they were doing before, which isn't specified. The claim above comes from http://www.haskell.org/aboutHaskell.html Whereas, http://www.erlang.org/faq/t1.html at 5.15 says that developers are as productive in lines of code (!!!) in ErlangLanguage as they are in CeeLanguage, but need five times fewer lines to solve the problem, which isn't unspecified.
The Erlang FAQ also states:
-
- The traditional ways of slowing down projects, like adding armies of consultants halfway through, spending a year writing detailed design specifications before any code is written, rigidly following a waterfall [WaterFall] model, spreading development across several countries and holding team meetings to decide on the colour of the serviettes used at lunch work just as well for Erlang [ErlangLanguage] as for other languages.
About ErlangLanguage especially: I think it comes with a similar component-level programming philosophy to most other FunctionalProgrammingLanguages, but has a very different inter-component communication philosophy. -- PanuKalliokoski
Considering automatic parallelisation, the ConnectionMachine was programmed in a dialect of LispLanguage. DanielHillis considered this the natural choice.
AliceLanguage is a step or two above Erlang, offering more than mega-concurrency. The Oz book (ConceptsTechniquesAndModelsOfComputerProgramming) studies Erlang, ConcurrentMl?, etc. and how Alice/OzLanguage encompasses all such capabilities.
Counterpoint Links
Some rather long, heated discussions concerning skepticism of claims of FP as a GoldenHammer, especially outside the domain of "systems software":
RefactorMe: merge with OoVsFunctional, FpVsOo?
CategoryFunctionalProgramming