I agree these are just claims, but when I look at the something like the following it is hard not to see the power that comes from simplicity.
;lazy-seq of Fibonacci numbers
(defn fibo
[]
(map first (iterate (fn [[a b]] [b (+ a b)]) [1N 1N])))
You can apply this to a larger set of problems and realize that issues can be solved with less code and that yields less errors. Correctness is also easier to achieve with FP because you don't have the typical problems of non-FP languages (index out of range in a loop for example), I think.
I personally think that the following has much more impact on modern CS than the Hughes paper linked above.
This is focusing on the reality (operating system threading model, no shared memory across processes -in the Erlang world-, communicate only with message passing, etc.) and this yields to a much higher impact. If you look into Scala features you can find many that came from Erlang, or through Erlang (some of them originally from other languages).
SCP also gave a bigger kick to CS (even though it has very little to do with FP) and it seems that FP languages were adopting it faster (I might be wrong on that).
> it is hard not to see the power that comes from simplicity
Actually, it is quite hard for anyone who's not already versed in Lisp and equipped with some reasonable knowledge of basic FP constructs such as folds.
It's also important to look at the whole picture, and the author of the paper (and FP advocates in general) have this interesting tendency to completely ignore the opportunity cost of using FP and to dismiss the advantages of alternative approaches over FP.
Personally, I think laziness and immutability come at a very heavy price that explains why only the superficial aspects of FP (lambdas) have been adopted while the rest of FP remains the realm of research papers and conferences.
> the author of the paper (and FP advocates in general) have this interesting tendency to completely ignore the opportunity cost of using FP […]
Are you referring to the disadvantages of using a non-mainstream style? That's not relevant here. We're comparing the styles themselves, not their popularity.
> Personally, I think laziness and immutability come at a very heavy price that explains why only the superficial aspects of FP (lambdas) have been adopted while the rest of FP remains the realm of research papers and conferences.
I have a much simpler explanation: first class procedures are compatible with imperative programming, while immutability is not. (And laziness needs immutability to be workable.)
People don't adopt FP because old habits die hard.
> first class procedures are compatible with imperative programming, while immutability is not
But immutability is not is not incompatible with imperative programming, otherwise people wouldn't be writing things like Guy Steele's "Lambda: the ultimate imperative" paper [1]. And of course, monads.
> People don't adopt FP because old habits die hard.
People don't adopt FP for the same reason they don't wear hair shirts; it is presented and marketed as an "eat your vegetables" affair.
Most reasonable definitions of imperative programming include the pervasive use of mutable variables, `while` and `for` loops, procedures that have effects beyond their return values, or plain don't return the same values for the same arguments…
You could de-sugar your way out of those (Turing completeness and all that), but then it wouldn't be imperative programming any more. You could isolate those things in a monad, but (i) the monadic part is not functional, and (ii) the rest of the program don't use those things. I stand by my incompatibility claim.
Your marketing argument is better, but I don't see any other way. No matter how you cut it, FP is big about not using some features, and what benefits we get from this restraint.
Haskell has been called one of the best languages for imperative programming [1]. Even in a pure language, we still NEED imperative code at some point where the program hits the real world of time and state (even in FRP a stepper is often needed!). By lifting state and sequencing into a monad, continuation, map or whatever, it is still there even if handled better.
Now, you don't need to use imperative programming everywhere, and in a functional language you have the option to easily not fall into it (well, in Haskell, most other popular FPs are way less pure).
> No matter how you cut it, FP is big about not using some features, and what benefits we get from this restraint.
And that is really why FP will be niche (especially pure FP). Like very powerful static type systems that are really good at saying no...it adds to the resistance of writing code while claiming benefits further down the line. "Worse is better" wins out over and over again (why dynamic languages, imperative programming, OOP continue to be popular; we aren't Vulcans after all!).
> Like very powerful static type systems that are really good at saying no...it adds to the resistance of writing code while claiming benefits further down the line.
My experience is the exact opposite: having a compiler that is good at saying no means I correct my errors earlier. With a dynamic typing, my errors are revealed later, and further from the root cause. So, static typing removes to the resistance of writing correct code. It speeds me up.
Static typing would indeed add to the resistance if it required you to jump through hoops. But it doesn't. Bad type systems have significant limitations, but the good ones have very few. Unless you go crazy with Smalltalk-like hot-plug live systems (and even then, see Yi and Xmonad), static typing is permissive enough.
> we aren't Vulcans after all!
I have two theories. The first is, some of us are Vulcans. And somehow, Vulcan brains function better with static typing and functional programming. In other words, Vulcans are better at "math", and put programming into the "math" bucket. Then there are humans, who see programming and mathematics as two quite separate disciplines, ran away from math, and function better with procedural programming and dynamic typing.
My second theory is that everyone could adapt to anything, if only they would bother to learn. Anyone can think like a Vulcan.
I currently lean towards the second theory, though frankly I'm not sure which theory is closest to reality.
> Static typing would indeed add to the resistance if it required you to jump through hoops.
No arguments there. Haskell makes some interesting tradeoffs in this regard, I'm not sure they are optimal but they are definitely valid.
> Unless you go crazy with Smalltalk-like hot-plug live systems (and even then, see Yi and Xmonad), static typing is permissive enough.
The PL community is just really bad at exploring incremental type checking technology. It is totally possible (and I'm doing it with the live programming language I'm working on).
I only claimed that: if static typing feels like it is resisting too much, programmers won't like it. How fluid is programming in Haskell? Ever try using it in a REPL?
> The first is, some of us are Vulcans.
Yep. Take SPJ, the guy is brilliant and I feel like we are from different planets when we talk.
> In other words, Vulcans are better at "math", and put programming into the "math" bucket.
Some programmers like to treat programming as math, but definitely not all of them or even a majority of them.
> My second theory is that everyone could adapt to anything, if only they would bother to learn. Anyone can think like a Vulcan.
Spock was never able to convert Kirk. And I doubt we ever wanted him to.
The average speaker would find Mandarin easier to read than any other language. That does not say anything about the effectiveness of Mandarin over other languages.
>I agree these are just claims, but when I look at the something like the following it is hard not to see the power that comes from simplicity.
What simplicity? That's even more complex to state than the traditional imperative solution, that's also closer to how mathematicians would write the equation.
I can't be the only one who thinks that implementing a toy function in one line of terse code doesn't demonstrate anything useful. What about programming in the large? What about efficiency of naive implementations? What about maintainability? These are things that actually matter in software engineering.
It's only anecdotal, but I find pure, immutable code far easier to maintain in any language. To a first approximation, a functional interface == a testable interface.
I've joined several projects in their maintenance phase which had no tests, and introduced some as I went about debugging, adding features, etc. Since the code was often untestable, I'd make a few refactorings over and over again to allow testing, and these just-so-happen to tease apart the pure computation from the effects; in essence making the code more functional.
An obvious example is to turn implicit state into explicit parameters, eg.
// BEFORE
function foo(x, y) {
b = x + y + a;
}
// AFTER
function foo(x, y) {
b = foo_pure(x, y, a);
}
function foo_pure(x, y, z) {
return x + y + z;
}
This doesn't make `foo` more functional or easier to test; but testing `foo_pure` is trivial. In particular this makes debugging logic errors much easier; since there's no need for elaborate/brittle test setup (eg. setting all the right globals, creating and cleaning up files, etc.).
Scrap the scare quotes, it is obviously false. Less code in the small does imply less code in the large. It doesn't need any justification, it is a tautology: if it takes less code to write all the small things in your program, the program itself will have less code overall.
Or did I misunderstood the meaning of "less code"?
Ok, sure, but I am sure there are related libraries for that kind of development. When talking about the real world, the majority of it is in web development or business apps.
I personally think that the following has much more impact on modern CS than the Hughes paper linked above.
http://www.erlang.org/download/armstrong_thesis_2003.pdf
This is focusing on the reality (operating system threading model, no shared memory across processes -in the Erlang world-, communicate only with message passing, etc.) and this yields to a much higher impact. If you look into Scala features you can find many that came from Erlang, or through Erlang (some of them originally from other languages).
SCP also gave a bigger kick to CS (even though it has very little to do with FP) and it seems that FP languages were adopting it faster (I might be wrong on that).
http://www.usingcsp.com/cspbook.pdf