The history of programming languages is one of my personal interest fields, and I find it fascinating how, 25 years on, many of the most popular languages are still slowly encorporating core features of functional languages like OCaml: records, enumerated (sum or variant) types, pattern matching and destructuring, true tail calls, type inference.
To be clear, I’m in favor of these changes, and I don’t denigrate any existing language for not having them, I just still marvel seeing HN headlines like “Python to get match statement”, “Record Types in Java”, “Tail Call support in Rust” and appreciate all the more the things OCaml (and before it, ML) have gotten right for so long.
Keep in mind that a language like Rust would've been effectively unusable in its current form 25 years ago due to the RAM and CPU requirements by the compiler.
As CPU and RAM increases you can make smarter compilers and generalize things like type inference, bigger compilation units and higher level constructs that rely heavily on compiler optimization for good performance.
Many people think that Rust and C++ are too slow to compile today, imagine what it would've looked like on a Pentium II CPU with 128MiB of RAM!
C++ 25 years ago (1996) was terrible. I used to have to keep a large C++ application going on GCC, Sun's compiler and Microsoft's compiler and it was a nightmare. Using templates with classes would invariably cause one or other of the compilers to crash, so we had to concentrate on the simplest subset of the language that worked. STL was very new and not supported on all platforms so we ended up reimplementing a lot of that in our own classes. Build times were glacial and the resulting binaries were enormous. Multiple string types. And horrific things like CORBA's C++ bindings ...
I have used C++ in 2001 with ROOT and it was a long wait most of the time. Depending on your codebase and libraries involved making compiling and linking fast was an art form
25 years ago it wasn't C++11, but C with classes. Less TMP noise, small compilation units instead of the source code of entire libraries being #include'd.
lol or MFC, I checked that out and subsequently pulled the power plug on my pc. Granted I'm probably not a very good programmer. heck my comment is probably not even on topic in this thread.
No. I was born in the 90s. in the 2000s I was mostly doing .Net and Java, started doing C++ seriously in 2010s until I discovered Rust. Have I got the C++ history wrong?
I was using both templates and the stl heavily in 2002. I started learning c++ in 94 or 95 can't remember. Turbo c++ did not have templates, before the 98 standard it mostly was c with classes. And lots of unnecessary inheritance and overloading.
Edit, should include that the experience in 2002 was on a corporate project which ultimately had many millions of lines of code, so not just some crazy guy in a basement. Lots of crazy people were in the basement with me.
> I find it fascinating how, 25 years on, many of the most popular languages are still slowly encorporating core features of functional languages like OCaml
Yes! Ocaml was my first programming language and I have been baffled at how languages I learned subsequently tended to miss what I considered basic utilities like proper pattern matching and tail calls (happily those ideas are now finally entering the mainstream).
I had several years professional experience, including functional programming, and still found it pretty rough going for a while. And even other professionals have often not even heard of it.
My observation (and, I believe the authors of How to Design Programs have some data about this) is that FP is only “hard to learn” if you already know how to program: you have to unlearn things like “for loops” and various techniques that rely on mutation and learn to think in terms of the abstractions FP provides you.
So the biggest barrier that I found when learning ocaml was there were just not a lot of resources or organic examples around.
What there is is usually for a specific course, or is published by like Jane Street or some shit and highly domain-specific as well. I just found it hard to dig myself out when I ran into trouble.
I definitely agree about the FP concepts being no more difficult or even simpler to learn. I used to teach introductory programming to adults and at first we taught loops then map/filter etc and told students to use their preference.
Almost universally they used map, including complete synthesis of the entire concept of iteration without loops. Like when presented with a loop, I once saw a student skim the internal logic, see that it was doing an array push inside an if, and call it "a filter loop." To him the filter was the concept and the loop the tool, which is I think backwards from a lot of us.
I discovered computer science in preparatory classes (a French thing that comes before engineering school, you can think of it as the first years of college) in France where it was the default programming language (I believe they now start with Python and include Ocaml only if you take some options).
Interestingly, it was the students with previous programming experience who had the most difficulties learning the language.
I have not found the reverse to be true, the Ocaml compiler is very strict, but it makes you attentive to details and types in a way that transfers well to other languages.
OCaml was also my first programming language. First year uni in Brazil, 2006! Thanks to a very tough French professor.
The class hated it/him. Type errors were nothing short of terrifying. `function has type (a->(b->c)->(b->d)) but should have type (a->b->(c->b)->d)` or such. If you passed the class (a big if), you'd move on to C++ and OOP and never see Ocaml/functional again.
I appreciated it for providing me so much understanding wrt mathematical thinking - functional programming, recursion, induction. Later on I took some classes/researching using SML.
Fast-forward ~12 years and I get into web dev and what I see functional programming trending!? Kinda funny... I want to get into it somehow, probably Clojure this time. It just resonates with my thinking - maybe a product of being primed for it all those years ago.
Exactly, started university in Paris in 2004 and OCaml was used to teach data structures for instance.
First year was Scheme and C, second year had Java, OCaml, more C, some C++ if you wanted and Mips. Third year added Ada and .Net if I remember correctly.
I'm not trying to be oppositional or take anything away from what you said about OCaml, but I'm interested in the evolution of programming languages and watching how the best ideas are borrowed or stolen and incorporated into new languages, sometimes with additions that improve upon the original. That's why I always check out new languages that are posted on HN. I like to see if the author has a new idea and then which language picks up on it. It's interesting to ponder such things as what will be the C++ response to Rust?
While not a lesser know language, the evolution of await/async from Haskell to C# to Dart by Meijer is a good example that comes to mind. I'm a working programmer without a college degree, so I can't vouch that I have the correct interpretation of the computer science. See "Confessions of a Used Programming Language Salesman - Getting the Masses Hooked on Haskell' by Erik Meijer
Programmers generally pick platforms and not languages. C became popular because of Unix and then Windows. JavaScript came with the browser. PHP came with shared hosting. Go sort of came with the "cloud". Java was made by an OS company, and it got new life with Android. So did Kotlin. Swift is for iOS, etc.
There are exceptions like Python and Ruby, but I think the "default" is that a given language is not popular, and there have been almost no platforms written in functional languages. (anticipating the objection: Lisp isn't functional :) )
That's really not the question. Any language that we've all heard of is pretty much by definition a wild success, comparatively. Most languages stay very small.
There are very large first-mover advantages and network effects to programming languages. Programmers want to learn languages existing code is written in; companies want to use languages that lots of programmers already know. Languages that get big for historical reasons tend to stay that way.
Mainstream adoption wasn't the main goal for a lot of functional languages when they were created: the aim was to develop ideas of how programming could be better. The surprising thing, really, is that people write real production in some of these languages, despite how different they are from what most programmers already know. We shouldn't be treating not getting as big as Java as some sort of failure.
Along other things, there was a heavy investment in marketing the languages that came at the same time as the likes of ocaml [1]. In more recent years, we've also seen that backing by a major company that can help building the ecosystem is a major factor, as happened with Go. Finally, some languages flourished because they offer access to a platform that would otherwise be inaccessible, as JS does.
Overall, though, functional languages see progression today, they may not have an exponential growth, but neither did Python, and look where it is now.
Ecosystem. It's not always about the language features, it's about how quickly I can get something working. Having a large, thriving ecosystem is a big part of that.
I’ll add an alternative answer to the variety you’ve gotten: functional programming is often given a bad name for not really corresponding to the way computers actually work. When you’re writing C, it can feel like the code you’re writing corresponds directly to the actual physical processes and components of the machine.
The more higher level you get, the less you feel that (no Malloc in Java, for example), and functional languages are fully based on a model of computation that isn’t the one we physically have in the real world. This can also lead to speed and memory problems, though I think at this point the compilers for these languages are good enough that this is less of a concern than it may have been.
It’s an interesting example of the Blub paradox [0] as well (Paul Graham’s answer to a similar question, “why doesn’t everyone use Lisp”)
What mainstream languages are you thinking about? Java is obviously the one that comes to mind when talking about market dominance, but it was created/supported by extremely wealthy corporations who invested hundreds of millions to push for its adoption.
Do you have others in mind? I'm sure we can find fairly similar circumstances for most of them.
Much as people credit Sun's marketing for Java's success, I think it would have succeeded even without them. Java successfully brought garbage collection to the majority of working developers at the time who were all C and C++ developers. This was a huge step forward that solved a massive pain point. Today this is far less of a compelling argument since most languages are GC'd and C++ is far less dominant, but Java was the right language for the time.
There was another big factor, remember that ISO C++ initial release is from 1998 and while C was standardised in 1990, many compilers in the mid-90's were still catching up to it.
Then POSIX still left too room for each UNIX flavour to decide how to actually implement certain features, e.g. signal.
So Java, despite being initially interpreted felt like how portable code should be, coupled with a rich library.
I recall a quote from an anonymous industry heavyweight when Java came out (paraphrased now because I can't remember exactly where I saw it): "Thank goodness, now I don't have to learn C++."
> Java successfully brought garbage collection to the majority of working developers at the time who were all C and C++ developers.
Isn't this what people refer as marketing? Other languages were garbage collected before Java. Common Lisp and SML both existed a decade before Java. There was also Smalltalk and Eiffel, but for them I've heard that Java being free really helped (which may be called marketing or not, but is still related to Sun money in a way).
- crowd maturity (zero dev cared about safety in the web 2 era, cue wordpress cheese, people flocked to php or ruby because it was fun and easy, only later people started to make solid specs for their languages)
- business-less ethos (I'd bet $10 FP dudes have zero desire nor skills to promote and sell their work)
- culture shock (fp is somehow very rooted in math culture, how many times in the last 20 years did someone at a meeting or an OO class said "explictVerboseVariableNamePlease" ? compare that to
fold f z [] = z
fold f z [h:t] = fold f (f z h) t
)
add various degrees of second degree effects like the fact that complex and hard to sell things don't attract funding, unlike wordpress you get less exposure. Maybe for the best because mainstream business interest would surely distort the original paradigm quest to fit whatever money-heavy requirement lands on someone's desk that day
fold is a library function that is very general, and would be built-in in most other languages (if it existed at all). You wouldn’t write most functions like that.
A long variable name only makes sense when the variable is specific. In fold, you have “a function”; nothing else can be said about it. And since working with “a function” is very common, Haskell programmers have converged on a shorthand for it: f. Sure, it’s harder for an entirely new programmer to understand, but every language has practices like this that need to be learned: take “i” in a for-loop in C.
That's quite removed from reality. In java8+ you'd have to import a BiFunction class to be able to talk about a fold. Don't underestimate the mainstream.
because they didn't have millions of dollars for marketing budgets or the one thing they did that could make startups make millions off their work.
If the French government had realised what they had in OCaml and made it the standard programming language in all of France they would be a software powerhouse by now.
Back when I was a student (circa 2000), caml was one of the "official" language to teach computer science in the first few years leading to engineering school ; and in my case, it also happened to be the first language taught to everyone in my eng school. So I guess the acamedic world was trying it's best. I remember joking with a TA that no one would ever write a line a caml professionally ; I can't wait to be writing reason or caramel at a gig :)
Functional languages are harder to learn than imperative languages, a big factor that I didn't see in this comment thread.
With imperative code, you can just spell out a for loop which makes intuitive sense. With functional code, you need to do so recursively, so you need at least some understanding of recursion, and perhaps even category theory for more complex examples or languages like Haskell.
Just that kind of complexity over an imperative language alone is why I surmise that functional languages haven't reached as much popularity.
You really don’t need to understand category theory to understand Haskell, or even recursion for simple examples. Recursion is frequently used to implement control structures that are either built-in or missing in imperative languages; users of these control structures don’t need to understand how they work.
Which is simpler:
for (int i = 0; i < n; i++) array[i]++;
or
map (+ 1) list
Admittedly, most modern languages have something like foreach, but one of Haskell’s major advantages is that foreach can be implemented as a library function.
For most people, the first one is simpler. The second seems simpler to us as we've used functional languages, but there's a lot going on there. What is map? It's a function that acts on a structure using a function, ie a higher order function. What is (+ 1)? An anonymous function that will be used. Contrast this to the more natural idea of, for each item in the list, increment that value.
You can argue exactly the same for the first example: what is for? Why is for a special construct and not a function? What is (int i = 0; i < n; i++)? What is array[i]++? What is n here?
The functional approach allows you to only care about the what ("add 1 to each element of the list") instead of the how ("create a number that goes from 0 to the size of the list minus one (because our language is 0-indexed, because arrays are in fact directly related to how memory is laid out), then for each value of this number, take the value that's at this index in the array and increment it").
I'd argue that the functional approach is easier to learn, especially if you haven't had prior experience with programming. You also said earlier than functional is harder to learn because you have to use recursion to make for loop. That's not really true, you can just use functions like map which are already here. And when you start tackling recursive data structures like trees, recursion is easier to understand.
To be clear, I’m in favor of these changes, and I don’t denigrate any existing language for not having them, I just still marvel seeing HN headlines like “Python to get match statement”, “Record Types in Java”, “Tail Call support in Rust” and appreciate all the more the things OCaml (and before it, ML) have gotten right for so long.