On topic:
I sometimes wonder if the wins from FP languages are lost on the people not already scarred by the pitfalls of imperative programming. I wonder the same about someone starting with Python instead of something more wordy and cumbersome. I don't think you really can appreciate the ease of use if you haven't already written tons of boilerplate or type information because the compiler is stupid.
At the same time you don't know the price of the ease you're getting, so there is a warped perspective on both the ease of programming and the performance of languages.
Haskell, I think, exists in a sort of middle ground where it's actually really fast but extremely expressive. Maybe someone uninitiated in programming won't have as many problems formulating functional solutions to problems in Haskell too.
The reality was that the tools were slower and buggier than others, the programs different (and slower) but no simpler and the bugs different but stilly just as buggy.
When presented so mindlessly and categorically, any claims of superiority instantly lose credibility. When reality is taken into account, even more so.
This aside, you seem to be talking about the languages themselves, so let's go ahead:
> the tools were slower
Which tools are these? I don't see this as a systematic failure of FP languages.
Which language were you presented with? Did they explain what you're trading your speed of execution for?
I'm asking these questions because it doesn't really seem like you got it and this supposedly being 20 years later it seems like you're purposefully not getting it. In these discussions I find that a lot of people believe FP proponents to be very unpragmatic, but I find that in most cases, such as this one, there is little to no concession made on the "other side".
Most FP languages are not suitable for performance sensitive tasks and most people will admit this. For most other tasks, though, they're just going to allow you to work faster and get to where you're going with less hassle.
I would like to point out that I'm not saying FP languages are just better overall or that an FP language is always the best choice, but I am saying that the principles they employ and teach undeniably are the best. The alternative isn't as much a principle as it is a lack of principle. Flipping individual switches and modifying memory is just not caring.
"doesn't seem like you got it" ... "purposefully not getting it" ... "principles [..] undeniably the best".
No, you like those principles best, and that's about the most you can say. We don't even have solid criteria with which to make that call, never mind there being any type of consensus as to which is "best" (except within specific communities, but with each community having a different consensus and the most closed-minded of these communities usually the most sure of themselves).
Just to head off more ignorant comments: I aced those courses, as well as a few more including the elective "foundations of FP" and did my oral exam on Backus's FP calculus, which inspired me to come up with Higher Order Messaging: http://en.wikipedia.org/wiki/Higher_order_message
I also did some courses on algebraic specification and graph grammars (related to category theory), as well as formal specification with Z (yes, aced those as well). While useful in certain very constrained areas, these techniques trade making the smaller problem better (spec -> code) for making the larger problem ( actual problem -> spec ) infinitely worse.
Of course, functional techniques are a part of my toolbox, as they should be for any professional. However, if they were the only contents or even the majority of my toolbox, I couldn't do what I do and have been doing for the last quarter century.
BS principles are not better than no principles.
Or principles that tie your hand around your back for that matter. And functional principles do that for a lot of cases, with respect to performance, memory impact etc.
Functional languages are not some kind of 2x or 10x multiplier of a programmers abilities. In fact most of the things that made LISP interesting have been ported since ages in modern non-functional languages, from GC to closures, and even macros.
>Most FP languages are not suitable for performance sensitive tasks and most people will admit this. For most other tasks, though, they're just going to allow you to work faster and get to where you're going with less hassle.
Not the case in the real world.
For one, this BS idea forgets all about ecosystems and libraries. Python will let you work faster and get where you're going with less hassle. Functional languages that have 1/10 the libraries available, and in various stages of abandonment because of lack of programmers will not.
>The alternative isn't as much a principle as it is a lack of principle.
Really? For one, what all "FP languages" do when they run, is "flip individual switches and modify memory". The way they model the program is just an abstraction (and a leaky one) from what happens in the machine.
Second, I thought the Church-Turing thesis shows that lambda calculus is equivalent to the Turing machine way, for one.
Third, where did you get the idea that non-FP languages don't have principles? Smalltalk, for one, sure has tons of unifying principles behind it. Prolog. Erlang.
And if Algol was good enough for Dijkstra, modern, 10-times better algol derivatives are good enough for me. Especially if they also have adopted tons of functional paradigms, which you can get to opt to use when it makes sense for your design, and not have them forced upon you.
I recently have been putting a lot of time into learning Haskell and it is amazing. The type system gives me so much confidence, and I have now reached a stage where writing Haskell programs is as concise and fast as writing Python programs, with a lot less bugs and a lot more extensiblity. The thing is that defaults matter. With Python, sure you can achieve a lot of this stability by using a lot of assertions, but who want's to do all that work to write a simple script. With Python, I used to have write once code that I would use for a task and chuck away. With Haskell and its abstractions, I reuse almost all of my code. I have completely replaced Python with Haskell as the programming language I use to do my daily work.
Sure, Haskell is very different from conventional programming languages and initially hard to learn since we all just want to change state. However, personally this style was surprisingly easy to internalize. Instead of modifing data, you are passing it through a series of pipes, transformers and filters to get your final result. It is very easy to reason this kind of code, though with laziness, Haskell makes it hard to reason about its exact performance.
> Really? For one, what all "FP languages" do when they run, is "flip individual switches and modify memory". The way they model the program is just an abstraction (and a leaky one) from what happens in the machine.
Well, all Python programs manage pointers in the end, and flip individual switches and modify memory, so functions and objects and all of that jazz are just leaky abstractions. We should all go back to assembly, or even better, flipping switches.
I believe the IO Monad to be a wonderful abstraction for what happens inside the machine. Monads are wonderful abstractions in general, and first learning how normal monads like the list, State and Maybe monads work is an amazing experience, but realizing how IO is just a special case of the State monad is mind blowing.
> Second, I thought the Church-Turing thesis shows that lambda calculus is equivalent to the Turing machine way, for one.
Yes they are equivalent just as Brainfuck is equivalent to Python, or C to Java, or Fortran to Smalltalk. These are all Turing Complete languages, so obviously they are equivalent!
> And if Algol was good enough for Dijkstra, modern, 10-times better algol derivatives are good enough for me. Especially if they also have adopted tons of functional paradigms, which you can get to opt to use when it makes sense for your design, and not have them forced upon you.
If assembly was good enough for Knuth, why are we not using that? x86 is good enough for me. Why are Algol derivatives forcing me to use the imperative style of code? Why can't I use a modern functional language and and use imperative, unsafe, statefull code when it makes sense for my design?
The problem is that defaults matter, and separating unsafe and safe code has a lot of advantages. Also, IMHO functional code is just easier to read and much cleaner. Instead of writing step by step instructions to the computer, we tell it what to do in a more declarative manner, because the lower abstractions can easily be separated out. Eg:- the canonical quicksort in Haskell [0]
[0] http://www.haskell.org/haskellwiki/Introduction#Quicksort_in...
The whole point of Quicksort is being a fast and in-place sort. That's its entire reason for being (the name kinda gives it away). An algorithm that's slow and not in place is not Quicksort and not "the essence" of Quicksort either. It's some other sort ("Slowsort"?) loosely inspired by a cursory reading of Qicksort and not understanding what Quicksort is about and why it is "quick".
The whole thing is somewhat typical though: "We have discovered that the essence of <well-known-thing> is <completely-different-thing>". No, you have discovered a mapping function from <well-known-thing> to <completely-different-thing> That's not the same as "the essence".
No, there are plenty of people who will debate this, programming languages academics even. There is a vocal FP crowd that fawns over elegance, but there are plenty of other people who are more pragmatic about it.
> I sometimes wonder if the wins from FP languages are lost on the people not already scarred by the pitfalls of imperative programming.
Pity the poor programmers who get things done, write huge beautiful systems, all without worshiping lambdas? And by taking shortcuts ala side effects as a way to making things easier.
> Maybe someone uninitiated in programming won't have as many problems formulating functional solutions to problems in Haskell too.
It depends on how much math they have behind them. You take a mathemegician, sure, but a high schooler who is still having trouble with pre-calc?
Very much so, and also depends very much on the problem at hand. Yes, compilers and yet another RB-Tree implementation can be great in FP. Most real-world problems aren't that. In fact, most real world problems I have encountered (and see) tend to be massively about manipulating state. Often they do little else than shuffle data around.
I sometimes think "computers" are misnamed, because they do so little actual "computation". "Data around-shufflers" might be more appropriate.
The functional programming language is Opal, a language developed at the TU Berlin, it has barely any documentation, a compiler that only works on Linux and OS X, that is if it works because it has quite a few bugs, it further comes with a REPL that sometimes produces failures the compiler doesn't and tooling is non-existant.
So as a new CS student you have to learn using Linux and setup a development environment by yourself with barely any documentation to go on. You then continue learning only the very basics of programming such as what functions are, if statements, recursion, big O complexity, a little bit of parsing and though it's called differently: monads. At the end of the semester you then develop a renderer for a regular subset of HTML that includes only <html>, <head>, <body>, <title> and <p style="text-align: {left, right, center, justify};">.
On top of that the language has a couple of weird features: Every function can be used as any kind of operator if the number of arguments fits. This means that the parser has often problems figuring out precedence rules and you end up adding parenthesis around every expression just to be on the safe side.
Number literals also don't exist. There is a pre-defined set of functions which don't take an argument and produce a number such a 1-12 or so, n^10 for a few n, and a couple of 2^n for a few n. All other numbers have to be explicitly converted from strings. In practice this means you do the latter all the time so 1 turns into ("1"!).
Furthermore variables are defined by name and type. You can have two variables called foo in the same scope, if they have a different type and depending on how foo is used (Opal has type inference) one of the variables is chosen.
The prior feature is effectively necessary because Opal also doesn't have polymorphic functions. It has polymorphic "Structures". A Structure is file you can import, within that file you can define a set of variables that are polymorphic, the types of which are defined by however is importing it either explicitly or implicitly through type inference.
This is pretty much like how you might use the pre-processor in C to achieve polymorphism.
Have I mentioned by the way that a Structure is actually just a header like in C? In the Structure you only define the types of the API, the implementation is in a different file.
So a functions like map requires writing two separate files. Luckily it's in the stdlib.
Overall these features are fine, if everything works nicely but if you have an error somewhere, the compiler can emit massive difficult to understand errors, not unlike what a C++ compiler might produce for code that uses templates heavily.
The language and the choice to use that language is heavily critized by pretty much all students, functional programming however is not. In fact pretty much everyone would prefer if Haskell (which is the functional programming language closest to Opal) were used. The only reason it's not, is that the current prof for that class lead the team who developed the language.
So we were spared that particular disaster, which was and is sold using the same "unquestionable superiority" rhetoric. Instead we dealt with Hope. As in "I Hope it will finish in the next 15 minutes". "It" being a 10-30 line program. Usually it didn't, instead producing a largish coredump.
Our Sun 3-50 diskless workstations didn't help, but hey, Turbo Pascal could compile + execute a hundred lines of code in a second or two on the Z80 card in my Apple II+, a computer with several orders of magnitude less CPU/memory than those Suns.
Later we also used another language, I think it was Miranda. That introduced us to the joys of type inference. Magical when it works, completely inscrutable when it doesn't, especially since you don't get feedback on the cases that do work.
The big problem here is not that the tools were buggy and the languages less than fully thought out, that is fine, if presented that way. The problem is the complete disconnect between rhetoric ("perfection", "everything else is steaming pile of manure") and reality (sort of the opposite).
In the meantime, tools have certainly improved a lot (ghc/ghci on my MacBook Pro are quite tolerable), but the disconnect between rhetoric and reality is still there, because everything else has also improved.
Consider Opal itself: an FP language (so one of the domains FP is actually good at) in active development for more than a quarter of a century by teams using magical, all-conquering, flawless-marvels-of-correctness-producing FP unicorn-technology by teams of programmers that are experts in said technology. And it is, quite frankly, a steaming pile of manure.
EDIT: Hope: http://en.wikipedia.org/wiki/Hope_(programming_language)
FP hasn't been given as much attention as imperative programming languages, especially not when it comes to the important last step of language development, which turns ideas that are nice in theory into tools that are actually convenient to use.
Java is a good example for how much that matters. The language is inelegant and makes it impossible to express yourself concisely nevertheless the tooling is incredibly good, so good that it makes up for quite a few surprises.
A FP IDE that for example shows you inferred types and type errors while you are writing the code, would already help a lot as it could much better visualize the problem, than a compiler that has to describe an error purely with text.
FP languages are not perfect, no language is but they have the potential to be much more powerful in lot of ways than imperative languages. Lisp is a good example for this although it's also a good example that such power can corrupt people to use macros in awful ways.
In any case when it comes to the rhetoric especially from professors, you have to take into account that they have spent their entire life specializing on what they are doing. Of course they are excited by what they are doing and even if they aren't they have a good reason to lie to themselves consciously or not because the alternative is acknowledging they wasted their life on bullshit. They are biased and that's ok, you just have to be aware of it.
Turbo Pascal for example was written by a single guy, Anders Hejlsberg, in about 2 years for several platforms in assembly language, and included an integrated (though primitive) text editor/IDE.
Smalltalk was taken from ST-72 to ST-80 in 8 years, with small teams that also had to invent/implement complete VMs, operating systems, bitmap graphics engines, GUI framework(s) and sophisticated IDEs. You write that it would be nice to have an FP IDE so it could give you better feedback (or were you talking about an existing FP IDE). These guys built the live IDE (even better than types for direct feedback) in a fraction of the time. Does OPAL still compile to C? Does it still use Tk?
Think about Ruby, Python, etc.
I could go on (the VPRI stuff is also amazing), but I think you get the idea: it seems that not only can you be a productive member of society without FP, it sure looks like people can be a lot more productive without FP than with it.
Java is not really a good example of anything. Certainly not of an OOPL: "Java is the most distressing thing to happen to computing since MS-DOS." "If the pros at Sun had had a chance to fix Java, the world would be a much more pleasant place. This is not secret knowledge. It’s just secret to this pop culture." — Alan Kay (who coined the term "object oriented")
I don't quite get why you see LISP as an example for the power of FP, it is a multi-paradigm language with some functional elements, and most of its power comes, AFAIK, from its meta-system.
And HOFs like map or fold have been in other languages since the dawn of time, they're certainly in Smalltalk.
In terms of rhetoric, Peter Pepper might seem like an outlier, but as far as I can tell he is not. You can see it in this very thread: if you don't buy the self-evident awesomeness, it must be because "you didn't understand" and "refuse to understand", it cannot possibly be because you legitimately have a different point of view.
Another example. I watched the following talk by Simon Peyton Jones on data parallel Haskell:
https://www.youtube.com/watch?v=NWSZ4c9yqW8
Interesting stuff. But he has to go and say it: "this is only possible in a pure FP language like Haskell". Hand raised in the auditorium. "Actually, this sort of thing is pretty common in the HPC community, in FORTRAN [under some specific name]". And of course he can't just shut up and read up on things he obviously doesn't know about, he has to retort: "well, that means that it is nothing but a variant of Haskell at this point". Ouch! And finally, at the end of the talk he gives some numbers. It turns out that this amazing thing that's only possible in Haskell needs 6 cores to match the performance of a single core C program. 6:1. That's absolutely pathetic, especially when compared to what the HPC FORTRAN guys are doing. So maybe he shouldn't be lecturing them, they know this stuff a lot better then he does.
Now don't get me wrong, the talk was interesting and thought provoking, but the mismatch between grandness of the rhetoric and the paucity of the results was its usual epically proportioned self.
That was a good 20 years ago, but I just ran into a current student who told me that's still the case, and they still hate it as much as we did.