Not sure where to ask this. Curious about the language Python and the feasibility of writing it functionally. I am very familiar with JS, much less so with Python. JS and FP is a decent marriage: no types, large FP ecosystem (e.g. Ramda). Of course it lacks a lot of the joys of Clojure, but I'd say it's probably feasible to think and write code in familiar ways as a Clojurist even if JS+FP is generally heavier on category theory. I know Python also is dynamically typed with data literals similar to JS (of course not as rich as Clojure's set of literals; pun intended), and that list comprehensions are a big thing in Python -- which is a nod to declarative coding, at least. Is Python and FP an similarly decent marriage? How does it differ? I generally see Python and JS as similar languages, with the exception of frontend dev.
Functions in Python are a first-class citizen.
But there's no syntactic sugar for call chains, no ergonomic immutable data structures, no structural editing (at least as refined as paredit), and it's chock full of dumb shit. Pardon my French, but I can barely tolerate it anymore, even though it used to be my favorite language many years ago. The thing that immediately comes to mind is how nobody should write def f(x = []): ....
JS with no libraries is also not something I'd use when other options exist, but at least it's more ergonomic when it comes to common tasks. It even kinda lets you approach the data in an "immutable" way - you can easily create new data based on the old data, instead of mutating the old data.
I do not know Python, but I know Ruby very well and it's very similar (OO, dynamic typing etc.). In Ruby you can do functional-esque programming, the main thing you lack is immutability. In fact, imo, high quality OO code looks very similar to good functional code.
I agree with the other takes, the lack of immutability is what makes Python an unsuitable candidate for functional programming to me. I think try as you might, at some point a data mutation will take place and this might lead to confusing behavior that is tricky to debug if you're not careful.
Yes, it is my belief too that high quality OOP takes most of the OO out of OOP. That would be my approach to coding if I were forced to code in C# again. But C# was too much of a headache: a forced type system that does not support functional structures well enough: it always got in the way of writing simple code. You wouldn't believe the crazy types I manually wrote in my naïve attempt of writing FP in C#. @p-himik I did assume libraries. If I were to write JS, the first thing I would do is to add Ramda as a dependency. Does Python lack a strong FP ecosystem? Is immutability cumbersome in Python? Not as easy as JS where you simply destructure an object into a new one? (Restructure?) I realize it might not be as performant without native support like Clojure, but usually that's fine.
For fun, this is one of the utility functions I wrote at one point, trying to "simplify" things:
Func, Dictionary>
GroupByToDictionary(
Func keySelector,
Func, TValue> elementSelector) => entityList =>
entityList.GroupBy(entity => keySelector(entity))
.ToDictionary(x => x.Key, elementSelector); You have the copy module which lets you do it: https://docs.python.org/3/library/copy.html
> attempt of writing FP in C#.
Just curious - have you tried F#? What are your thoughts on it?
> Does Python lack a strong FP ecosystem?
No clue, I'd ask an LLM about it. But I doubt it.
Back when I was using Python for work and personal projects, there were no such libraries at all. In fact, in public discussions functional approaches were largely disparaged. "Don't use map where you can use a list comprehension".
> Is immutability cumbersome in Python? Not as easy as JS where you simply destructure an object into a new one? (Restructure?)
JS:
const m1 = {...}
const m2 = {...}
const merged = {...m1, ...m2}
Python:
m1 = {...}
m2 = {...}
merged = {k: v for d in [m1, m2] for k, v in d.items()}Yikes.
Alternatively, dict(list(m1.items()) + list(m2.items())). Not better though.
But why do you ask this in the first place? If you want to use FP, I'd say it's much better to use a language that was designed with FP in mind. Otherwise, you'll be forever going against the grain. FP in Python won't help you write better code, won't help you land a job, etc.
No, I haven't tried F#. The little I have seen makes me want to avoid it: so much syntax. I really love Clojure's minimal syntax. Clojure is the only language I've willingly decided to learn without having a direct need for it. No other language has seemed interesting enough to invest time and energy in. I'm asking because if I don't manage to land a Clojure job eventually, I'll have to do something else, most likely in a non-FP language since I wouldn't be an attractive hire in F#/Elixir/etc. Then my priority will be to not hate my life at that job. Mostly exploring to see what languages are possible to work in on a daily basis without dread.
Oh, hold on - I'm actually wrong. You can do {**m1, **m2} in Python. Well, I stand corrected here.
> if I don't manage to land a Clojure job eventually, I'll have to do something else, most likely in a non-FP language since I wouldn't be an attractive hire in F#/Elixir/etc. Then my priority will be to not hate my life at that job Speaking purely out of my ass here (big surprise), but I'd wager that it's easier to find a Clojure job than it is to find a Python job where your colleagues would be tolerant of FP approaches. JS is more welcoming here, I have even seen Ramda in job requirements.
I know Python doesn't and probably never will support TCO, which is not the case in JS. So you're probably right; the pythonic paradigm is probably relatively anti-FP.
It's interesting to see that you find F# a verbose language, I would say it has struck a decent balance between its inspiration (OCaml) and the realities of being hosted on .NET
As for Python, yeah I agree that it's not ergonomic to program functionally in it. As a total novice programmer years ago it was the first language I tried, and I remember being immediately drawn to features like comprehensions and the stuff in functools. But then I had the thought, "these are cool but they must be easier to use in other languages"
I didn't mean it's verbose. I just don't like special syntax. I know F# too little to judge it conclusively, but that's my first impression of it. Maybe it's not bad as C#, where new syntax is invented with every version and hailed as the greatest thing ever by the C# community, but it seems to be excessive still, based on the little I have seen.
ah, I see. I've dabbled in F# and I can understand that gripe. From what I've heard it's actually a sort of proving grounds for syntax that gets added to C# eventually. Though I think it has some really cool features, like computation expressions (really just monads with a name designed not to frighten .NET devs)
Specifically, I think it was a case of pattern matching I saw, that instantly turned me off.
Interesting, I suppose I am biased in favor of statically-typed FP langs, because good pattern matching support is the thing I miss the most when writing Clojure
(Otoh Erlang and Elixir have cool intuitive pattern matching that is completely untyped)
My opinions on F# are probably not worth the pixels they are shown on. I'm sure it's not as bad as I think it is.
(Above last statement necessarily false if applied recursively.)
I get the sense that F# and Scala, while being idealistically developed and marketed as more ergonomic alternatives to their OO cousins, end up attracting people in inverse proportion to their familiarity with the host runtime and language of record
never used F# but read "Domain Modeling Made Functional" and the type systems looks pretty cool.
As for improvements(?) to Python, I discovered https://github.com/lihaoyi/macropy the other day... And then years ago I was also looking into https://coconut-lang.org/
In my experience Python is good for the libs and moderate portability, and that's mostly it.
As others have pointed out, it very much doesn't lend a hand to FP, and that's by Guido's own philosophy. Everything resembling an FP feature had to be rammed into it by overwhelming force.
I don't feel like the lack of immutable structures is the real problem, you can pretend the core structures are immutable just fine and the stdlib won't mutate them under your nose unless you clearly ask for it; efficiency will be sent to the hot place downstairs but you're already using Python. Modern libs also lend themselves more to data-oriented programming honestly, e.g. pytorch is very much about composition, polars has emerged as an immutable first alternative to pandas, and so on.
The problem for me is the deliberate lack of support for expressing functional idioms. lambda is crippled by the time-honored tradition of inanely distinguishing statements from expressions, infix syntax is tied to OOP...
One thing I'll say is that it is much more fun to program with once you kick something resembling a Lisp style REPL out of it, which isn't actually that hard to do. But alas, fun is not necessarily efficient, especially today in the Age of AI™
I'll just second the sentiment here that you will struggle to find a job in any mainstream language where your team mates will tolerate an FP style of coding (except, perhaps, JS), and with most mainstream languages you will constantly be fighting the inherent OOP-ness of the language to write FP-style code. I'll also note that if you are applying for a mainstream tech stack role, you will be competing with thousands of other candidates. If you apply for niche tech stack roles, you will be competing with tens or maybe at "worst" a hundred candidates. When we opened a junior JS role, we had 1,000 applications in a short space of time, and we're a tiny company no one has ever heard of!
I wouldn't be applying as a junior in these mainstream languages. I think that's the big difference. Btw, thanks for the insights, everyone. I shall continue to ignore Python!
I don't think junior-or-not makes a difference to the numbers game here, to be honest. It's a brutal job market at every level right now.
If anyone is using Windows (with WSL2+Clojure) — may I request you to run the tests and see if you can reproduce the issue? https://github.com/plumce/plumcp/issues/10 (I don't have Windows so can't test by myself. If there's a better channel for this message, please suggest.)
I'm pretty sure they saw it, if nothing else because of this one: https://daringfireball.net/linked/2026/01/05/hard-to-justify-tahoe-icons