I've been thinking about learning something new, so I went to Stack Overflow Surveys to see what technologies are people actually working on right now, and I saw this:
The top paying programming language is Clojure? Followed by F#, Elixir and Erlang, and a few positions below Scala and LISP, I'm impressed.
I don't have almost any knowledge in functional programming, I've heard that has better performance in certain situations (like managing big data), is more predictable, and more readable, but I don't see real use cases for functional programming instead of a traditional approach.
What are the advantages of the functional paradigm? In what situations are this languages used? For someone that wants to learn something new, what language do you recommend to learn first? I thought about Haskell or Clojure.
Thanks! 🙌
Oldest comments (28)
Certain approaches to frontend development with declarative tools like React have a lot of functional programming even if it's not strict, purely functional.
I think if you're used to that kind of development, playing around with a more functional tool like Elm — to learn — will probably help give you some perspective.
Other than that, I'd say that Elixir seems like the friendliest "backend" way to get into the functional approach.
I agree that the majority of elixir programming involves thinking functionally, but at it's core implementation, the focus on actors reminds me of the contrast between akka and cats/zio/etc in scala. I have always considered actors to be the OO taken to it's logical conclusion, where each actor is an object that operates concurrently. In the context of scala, Akka seemed to represent the OO / java programmers coming to Scala, whereas cats and other Haskell immitations used other approaches to concurrency. (Maybe the best way to put it is the following: the local, happy path in actor processing is functional, the global and resilient path in actor systems is more imperative.)
Regardless, using elixir as a way to learn functional programming basics sounds useful, and similar to elm on frontend, phoenix provides a batteries included backend context for writing small functions and seeing them work together.
With all things, there is a balance. To answer your immediate question, why do clojure devs command such a high income, it's because it is considered a "niche" language, and imagine an important system was developed in clojure and you need to hire a clojure dev to maintain it. Of course they will be able to command a greater salary if they have a history of specialization with clojure.
To your broader question about functional programming. It's great! There are a lot of benefits to it in terms of mocking, other types of testing, etc. Personally, I think that javascript & go have very "balanced" implementations of functional programming. They both allow for many functional programming patterns without going overboard and still enable many object oriented patterns. Following a "mixed" approach to object oriented and functional is a very mature orientation in my opinion as you begin to learn which technique is modeled best by which approach.
I would use a functional programming language if I were building something deeply complex such as a compiler or if I was building something which aimed for bulletproof correctness such as safety critical systems or systems dealing with financial transactions. For most other situations, where you are building something large but simple, I would only use functional languages if they were the dominant paradigm some day, because otherwise you will get small gains in exchange for sacrificing access to large sets of libraries or spending lots of time adapting libraries written with other paradigms to work within your functional programs. Huge ecosystems use and enormous numbers of engineers have been trained to use oo and imperative programming. In such an environment, it almost doesn't even matter that functional programming exists or if it's better or not. Some elements of node and reactjs have pushed industry slightly away from imperative or oo for everything, but I don't know if it will extend further.
If you want to learn functional programming, I would start with Elm, then clojure, and then go on to Haskell (or purescript if you want a more recent, fewer standard library warts version of Haskell). If I were looking to use something that uses some ideas from functional programming in production, I would learn rust.
One real-world application of functional programming (Mainly immutability) is in Redux's reducers. They receive pure functions (Functions that have a predictable output Y, given an input X) and should always return a new state, not modify the current.
When a technology is less popular it's hard to find a developer, you need to pay for relocation, etc. Salaries go up but job security is down. You want to change jobs and you're stuck.
You should very much learn functional programming as well as OOP and give yourself a well rounded education. But I would suggest correlating the salary information with the popularity information and the job listings in the area where you want to live.
The best salary information that I have found so far is levels.fyi and the "trimodal" article.
Others have pointed out: FP controls complexity. This leads to the ability to develop faster, with fewer people, and greater reliability.
As an example, I was on a team of about 8 devs, building a database in Java over several years. It was released as open source, and I maintained it for several more years. It was about 100k lines of code.
In recent years, I wanted to explore some more ideas, and implemented another, similar database using Clojure. This time, I was on*my*own, and did much of it in my spare time. The end result is about 7k lines. It’s been deployed in products with over 120k installations, and it works. I’m not the only one who’s done this either.
As for availability of developers, FP is so much more fun to use, there tends to be a sense of evangelism around the languages that provide it. Developers are also enthusiastic about getting more people to use their language, since the more it’s in use, the more likely they are to find a job using it. There are lots of resources for learning these language, and many people happy to teach it.
Clojure used to be very niche, but it really has expanded. It’s used by Cisco, Walmart, Target, several major banks (Capital One, Citi, Deutsche), and many more. NuBank relies on it so heavily that they bought the company that supports core development of the language. So there are many developers using it, and many companies in the real world relying on it.
Are the two DBs comparable feature-wise? Would you have been able to develop your DB before the old one with the same outcome?
Can someone else understand your code as well?
You can write super tiny code in an OO language too, but noone would be able to decipher it. (I once got a project like that ...)
I've seen small functional codebases. They were smaller because like in a typical java project you have 1000s of lines of code defining DTOs, entites etc. Guess what, the functional projects just didn't have that. It was all some generic form of lists and objects being passed around - pure guessing, no proper autocomplete etc.
I hated it. It felt so unproductive.
In order:
I did feel less productive in my earlier days. But this shifted over time. It's the complete inverse for me now, and that's despite having 20 years of OO experience.
Concepts of functional programming like Immutability and pure functions are very desirable for most kinds of backend applications as it naturally leads to thread safe and decoupled apps.
My theory is that object oriented got really popular because it made monoliths manageable (thanks to design patterns and clean architecture) but in the age of microservices and parallelism, FP is occupying a space that used to be OO exclusive.
Here has a good article explaining why OOP and C syntax got popular
cs.stanford.edu/people/eroberts/co...
My real life experience - as React FE developer - is: 100% help the functional programming for keep the codebase clean as possible, plus development and testing time also improved a lot.
Hello! I am Peter and do not use this two years ago.
In my judgement Haskell as a first exposure to functional programming (FP) would be a mistake for most people.
Having to wrestle with recursion is par for the course with FP but with Haskell you also have to concurrently deal with purity, static type checking and laziness—all powerful stuff for sure—which can quickly ramp up the challenge to painful levels.
Clojure is what worked for me but I'd only recommend that to people who are already familiar with the idiosyncrasies of the Java ecosystem.
Exhibit A:
Transcript
The point here is to internalize that just because something isn't easy doesn't mean it's difficult (just different) and that easy doesn't imply simple or vice versa. Simple doesn't complect while easy often does.
Fall back on this anytime FP feels different enough to seem difficult—you're just not familiar enough with it yet.
Exhibit B:
Transcript
This highlights why FP seems so different:
Imperative programming describes the "flow of control" (think flowcharts) where program execution moves computation forward by manipulating values in place (PLOP - Place-Oriented Programming)
Functional Programming advances computation by creating new values through the transformation of existing values (value-oriented programming). A functional program's description focuses on the "flow of values" (not to be confused with dataflow programming) rather than the "flow of control" .
I would go as far as saying that value-oriented programming is often what is meant when people talk about functional programming.
The Structure and Interpretation of the Computer Science Curriculum
This paper makes the case that it is often easier to learn FP before imperative programming as opposed to the other way around. This could go some way towards explaining why people who became familiar with imperative programming first, claim that imperative programming is more natural—it really is a case of what you were familiar with first.
One language that has been extensively used to teach FP is Racket; together with something like the "The little Schemer" it can be used as an introduction moving towards value-oriented programming (Systematic Program Design).
That said both in Clojure and Scheme the parentheses can take some getting used to; for most people it just takes some determination and persistence.
Personally I found Erlang to be a good way to learn FP (syntax notwithstanding), unfortunately some learning opportunities seemed to have dried up. Elixir could be a good substitute as long as you are vigilant and not let its Ruby-ish syntax guide you to more imperative implementation patterns.
Elm has already been suggested—these days I would tend more towards ReScript as that can also be used server side. I'd combine it with an exercism track to become familiar with it.
An earlier, very similar comment of mine.
Thank you so much for the detailed answer! This clarified a lot of misconceptions about FP, I'll definitely look into all the resources provided, I was using functional programming without even knowing it, I now understand why it seems more readable, because it's more predictable. Thank you again for your time 🙏
I would vote for Elm over Rescript for learning functional programming basics. The backend Rescript landscape is very early days and I wouldn't take it into consideration when choosing between Elm and Rescript. For backend, I would learn more established backend functional languages as my first exposure to backend functional programming.
I'm going to plug my own stuff here--I wrote a deep-dive series on functional monads in (primarily) object-oriented languages.
I wrote one on replacing nulls which is sort of similar to the null-object design pattern in object orientation and another brief one on extending that functionality to list processing with missing data.
But if you read any of them you should read Safer Data Parsing with Try Monads in which I argue that runtime exceptions are always entirely avoidable because you can chose to wrap all unsafe data in try monads which in effect causes the type system to enforce try/catch behavior to define all possible code paths.
I don't just want to plug my site for its own sake but because these are all libraries I've written for work and use on the regular, and they make my life so much easier.