I want to learn / use a functional programming language.
That’s a good idea.
With over 20 years of programming in languages like C, C++, Python, Go, Pascal, Forth and so on, I think functional languages are often easier - in the same way that programming without lots of global variables is usually and objectively better. There are of course a few domains where the OOP approach works better, like defining data structures with tight invariants, Linux hardware drivers, or simulating ships.
Or sometimes, you need a bit of imperative code for a number-crunching core.
But most code can advantageously be represented and structured as:
input -> transformation -> output
and the transformation part, which is almost everything which is really interesting, is where the functional style shines.
Now if you want something beginner-friendly and practical, it depends on what you want to do. Here my ten cents:
For systems programming, signal processing and embedded stuff, I’d totally recommend Rust. It has certainly a bit of Algol syntax but that’s rhe proverbial wolf in sheeps clothing: Many concepts actually come from OCaml, as well as the first Rust compiler. This would also answer the question whether functional languages are relevant and useful in industry.
If you want to do concurrent server-side programming, I believe there is nothing better than Clojure - perhaps with Babashka for scripting and ClojureScript for the Browser. Clojure is also incredibly elegant and concise, and at the same time it can use Java libraries, so it has huge library support, a battery powerhouse included.
If you learn both, you will see that Clojure and Rust have actually a lot in common in their approach to concurrency, which is preventing shared mutable state. It is great to learn both.
If you want a very practical, well-documented, and beginner-friendly language that also has great GUI support, I’d recommend Racket, a Scheme descendant. Like Clojure, it supports gradual typing.
If you want to program close to the Unix/Linux environment and want a simple as well as powerful language, a Scheme version could be a good choice. Personally, I love Guile, and use it where I previously used Python. Guile is very easy to use as a extension library for C and C++ programs or to control low-level code written in C. It also has a quite good REPL and debugger support and thus, interactive experience.
Speaking of Python, it has a great vector library which is heavily influenced by APL and functional designs, named Numpy. A C++ analogon would be Eigen. You see that functional programmers subversively introduce their filth everywhere!!
For data analysis, Scala could be an option. It is like OCaml on the JVM. Similarly, F# for .NET (but who wants to get entangled in Windows?).
If you want to keep it more multi-paradigm, you could chose Common Lisp - it will let you program in many styles and its SBCL implementation probably has the best performance after Rust. But Schemes like Guile or Racket are more geared toward a functional-preferring style. And if you want Lisp with stricter typing, there is Coalton - but I have not tried that last one.
For your goals, I would stick with Python unless you want to learn another language. There’s not much value to switch away when all the tools you need are primarily designed for Python.
As far as functional programming goes, with AI stuff, my experience is that you generally are more interested in orchestrating services than FP. For example, run input through model #1, then based on the output, run one of these other 3 models (or multiple of them in parallel), then eventually pass it all back into another service/function to aggregate and format the outputs. You can think of each of these as being “functions”, but they’re much higher level than what you’d traditionally consider functions in FP and more along the lines of microservices.
You don’t actually need to know any of the functional programming languages to work in the AI sphere. Moreover, codebase in pure funcional languages is hard to understand and maintain, that’s why they are rarely used in production. Of course you can learn any language for funsies, but I’d recommend Kotlin as a modern hybrid OOP language with a solid functional toolkit
Moreover, codebase in pure funcional languages is hard to understand and maintain, that’s why they are rarely used in production.
hahahah how to trigger a lot of people working with these pure functional languages (like me).
I’ve worked with both “normal languages” like C++, java, Perl, javascript (node + UI), etc… and then I switched to Haskell and Clojure. And our current production code is a LOT better than in traditional languages. In particular, maintenance is a lot cheaper that what I was used to when working with more traditional languages.
Regarding the community impact I would advise to use Clojure instead of Haskell (or Purescript, or Elm). Clojure is a nice middleground that has a huge advantage of being very stable (by that I mean, the code you write today will probably be very easy to deploy in 10, or 20 years from now).
Note however, the language alone is not sufficient to write good code, but it helps you choose better abstractions that will be easier to maintain. If you dive into the spirit of the language, you will have a better intuition and understanding about state management of big applications and will probably make more visible some design issues.
It depends on when have you switched from those “normal” languages to functional, and where do you work now. Java 10 years ago is not Java nowadays, and not Kotlin. These modern languages influenced by advantages of functional languages, and you can even write thr most of your code in the functional style.
Our company has some codebase in Clojure and Haskell, and it was a huge headache to find a substitution for a Haskell engineer when they left. There are so few experts on the market. But of course, if you’re an American big tech company, you’ll find an engineer.
And I’m not saying to you “hey, switch to Kotlin!” Nope, if you’re enjoying what you’re doing and it brings you money — keep going. But the sad reality is that it’s much harder to find a job for a pure funcional coder.
Moreover, codebase in pure funcional languages is hard to understand and maintain, that’s why they are rarely used in production.
This is incorrect. They are rarely used because procedural languages have momentum. It’s way more likely you’ll get Joe Codemonkey to learn and be productive quickly with functional features added to a procedural language than to learn and be productive quickly with an entirely different paradigm. So that’s what happens.
So, basically that’s what I meant, but without disrespect to Joe :)
Fair. I just think is prudent to draw a line between natural difficulty and cultural resistance to change.
This is incorrect. Functional code bases exist in many production environments. Twitter (pre musk) migrated their bloated code base TO Scala because functional code bases are easier to maintain and understand.
If you think about it, it makes sense, side effect free code will be easier to maintain just due to the lack of side effects.
As I said in another response here, it’s incorrect to compare Java 21 or Kotlin and Java 8. You can rewrite your bloated slow Java 8 code in functional reactive approach in Java 21 as well.
You can make a mistake writing any sort of code. What actually matters if it’s readable enough to catch the bug. I would argue that functional languages is the best option here, especially when we’re talking about about huge enterprise applications on complicated frameworks like Akka or ZIO.
Your crossposted question was a choice between Clojure and Common Lisp. Between the two I would say Clojure is more functional, but it comes with the baggage of the JVM. Common Lisp on the other hand is more of a 1980s language where you can use a functional style some of the time, and with some pain.
If you want a Lisp-like language, the usual starting point is Scheme, and if you want something with more creature comforts, try Racket. Either way, you’d start by reading SICP (fulltext here). But I think that whole approach misses out on an important aspect of FP, which is how type systems classify values.
So I’d say go with a typed functional language. OCaml is something like what you are used to, while Haskell is more “drinking from the fire hose” (steeper learning curve, but I think you will get more from it).
For Haskell, learnyouahaskell.com is a good place to start. I don’t know if there is something similar for OCaml. Haskell can be seen as a gateway drug to even more pointy headed languages like Idris.
Yet another thing to look at as a possible migration point from Ruby is Elixir. It’s not really so FP, but it’s very practical if you’re mostly interested in web development rather than programming languages per se. It’s dynamically typed like Ruby and uses Ruby-like syntax, so you should be able to switch to it fairly easily.
Clojure debugging is a pain because of the thousands lines of Java stacktrace. I really can’t recommend this.
Common Lisp on the other hand is more of a 1980s language where you can use a functional style some of the time, and with some pain.
Isn’t the main issue with it that you’re not forced to be functional? It’s supposed to be pretty good at it with the correct libraries.
Either way, you’d start by reading SICP
You really don’t want OP to learn lis
Isn’t the main issue with it that you’re not forced to be functional? It’s supposed to be pretty good at it with the correct libraries.
I’d say CL’s main issue is that it’s anachronistic by now, and when used idiomatically it’s an imperative language (think of LOOP). You can use some functional idioms in it, but it gets painful to do so.
Look at the article “Why Functional Programming Matters” and imagine rewriting the code examples in Scheme (confusing but straightforward) and then in CL (ouch).
Most ML development is done in Python to my knowledge. The reason is mostly the readily available side packages like torch, scikit-learn, etc. And Python, although not constructed as such, does indeed support a functional style. A quick search revealed a HowTo:
As a data scientist working in ML: it’s essentially all python outside of some really niche stuff
Elixir is a nice functional language. Not as purely functional as Haskel mind.
It is based off of Erlang and runs on the Erlang VM. Syntax is Ruby inspired. It is not a high performant language (like C, Rust, etc), but it excels at distributed computing and fault tolerance. There is excellent documentation and tooling for it as well.
I recommend picking up Graham Hutton’s short text Programming in Haskell, Second Edition. Even if you don’t end up using Haskell in “real work” (and you might!) it will teach you a remarkable number of things about how functional programming works.
Is Haskell the language that differentiates between pure and impure functions? I’ve never seen a single line of Haskell, but I watched a number of YouTube videos and I agree that experts explaining the language is eminently helpful to understand functional programming in general.
Haskell doesn’t have impure functions. What you’re calling impure functions (functions that produce values in the notorious I/O monad) are actually pure functions, that produce what you could think of as programs that run in an impure interpreter that’s outside of Haskell itself. Don’t worry about understanding that in detail until you’re deeper into learning Haskell, but at that point it will help demystify what the I/O monad (a traditional stumbling block) actually is.
The first few pages of learnyouahaskell.com will give you some sample code to show how clean the language can be.