It's not 'functional programming' that makes the code unreadable, but overly long chains of array-processing functions. Sometimes a simple for-loop which puts all operations that need to happen on an array item into the loop-body is indeed much more readable.
It's very similar to applicative style in FP. Conceptually, method chaining is equivalent to nested function application, it just comes with syntax sugar for specifying the `self` parameter.
As soon as you stop calling it "method chaining" and start calling it "function composition".
If you chain together a bunch of methods ('.' operator) in an OO setting, that's called a "fluent interface". It's a sign of good design and is to be commended.
If you compose a bunch of functions ('.' operator) in an FP setting, it's an unreadable mess, and you will receive requests to break it into separate assignment statements and create named variables for all the intermediate states.
This is becoming increasingly true as the years pass and the number of times I've had to drop whole mature architectures and reimplement something worse because some engineer's feefees got hurt can no longer be counted on my fingers & toes.
When writing code you have the motto "don't make me think" in mind, but how to know what's the maximum level of trickiness for readers? There are familiar techniques and idioms when it is your main programming language, but they are not for someone using this language on the side.
In any case, neither code nor comments should be tutorials. To a reasonable extent, it is up to the reviewer to do their homework or just ask. Then based on that interaction you can add a comment or a parenthesis, or uncompress a bit the code. But not to the point that it means to "dumb down" things, because it is a downward spiral.
I disagree with this phrasing. We’re engineering after all. The entire job is thinking. If someone doesn’t want to think, then they shouldn’t be a programmer.
Readability matters, though. I try to have a narrative structure in my code, so it leads the reader along. Formatting matters. And documentation helps. If you want to introduce an unfamiliar idiom that might be more functional, good, but document it. Share it with the team and talk about it. I know that writing and reading documentation is usually seen as a waste of time unless you’re doing it for AI, but I’ve seen it work well in multiple teams. In my experience, the teams with poor docs have the worst code.
class User:
def calculateCoworkers() = {
this.coworkers.clear()
for { d <- this.departments }
this.coworkers ++ d.employees
}
and then, somewhere else... user.calculateCoworkers()
... many lines after ...
for { c <- user.coworkers }
... do something ...
Yes, I've seen code like this many, many, many times where class members are used as "global variables" to pass state across functions. And I've noticed AI likes to generate code like this too (possibly because of the former (large presence of this "pattern" in the training data), which means I'm encountering this now in pull requests...What gave FP a bad rep is, i guess, Haskell (and the "pure functional approach w/ monad transformer stacks").
Every shop I worked at the devs were already at a level that they'd appreciate FP code: easier to read, refactor and test.
The tendency is also towards FP: see the features in recent Java/C# version. Or languages that gain popularity recently (Kotlin, Rust) are more FP'ish than their predecessors (respectively Java and C++).
skybrian•1h ago
Code review or pair programming might help here, to learn the team’s common idioms.
IshKebab•1h ago
1. Global type inference.
2. Implicit syntax (no brackets for function calls, commas to separate arguments, semicolons to end statements/expressions, etc.)
3. Currying & point free style.
4. Tendency to have very deep nested expressions. The gap between `let foo =` and it's actual value can often be hundreds of lines.
I'm sure you can write FP code that avoids these issues and is easy to follow but it doesn't seem like people do that in practice.
Rust avoided all of these issues fortunately.
(Oh I forgot about monads.)
amluto•25m ago
Conversely, a lot of code written in imperative languages would be clearer and/or less bug-prone if it avoided mutable state and used persistent data structures.
I wish there was a mainstream, high performance language that made both styles equally ergonomic.
walleeee•12m ago
delta_p_delta_x•9m ago
Unironically, C++.
jen20•18m ago
jazzypants•52m ago