What’s so great about functional programming anyway?(jrsinclair.com)
jrsinclair.com
What’s so great about functional programming anyway?
https://jrsinclair.com/articles/2022/whats-so-great-about-functional-programming-anyway/
569 comments
One take away from functional programming that I have incorporated into my Java (and C#) code: If/When possible, never (ever ever!!!) re-assign a local variable. (Rare exception: Classic C-style for-loop iteration with mutable `i` integer variable.) Really, really, I am not trolling / not a joke. How / Why? How? All primative parameter value must be final, e.g., `final iint level`, and local variables must always be final. Why? Final vars are significantly easier to "reason about" when reading code, as compared to non-final (mutable) vars. If you are using containers, always, always, always use immutable containers from Google Guava unless you have an exceptionally good reason. Yes, the memory overhead will be higher, but big enterprise corps do not care about adding 4/8/16 extra GB RAM to host your Java / C# app. Yes, I know that any `Object` in Java is potentially mutable. As a work-around, try to make all `Object`s immutable where possible. On the surface, the whole thing / exercise feels like a terrible Computer Science nitemare. In practice, it becomes trivial to convert code from single-threaded to multi-threaded because most of your data classes are already "truly" final.
I'm sure this is a wonderful intellectual exercise in computer science and math, but if this is to be the advertisement in favor of functional programming, I wouldn't consider myself a customer.
You start out with code that will not win any beauty awards but it gets the job done. It's easy to understand by programmers of any seniority, it's simple to debug and reasonably easy to put in an automatic unit test.
Next, you add all kinds of vague, poorly named meta utilities that don't seem to solve any tangible real world problem. You even mess with built-in JS methods like map. The code is now harder to understand and more difficult to debug.
A massive pain is added for some theoretical purity that few even understand or will benefit from. I'll double down on my rebellion by stating that the portability of code is overrated.
Here we're writing code to format notification objects. In our overengineering mindset, we break this down into many pieces and for each piece consider reusability outside this context to be of prime importance.
Why though? Why not just solve the problem directly without these extra self-inflicted goals? The idea that this is a best practice is a disease in our industry.
Most code that is written prematurely as reusable, will in fact never be reused outside its original context. And even if it is reused, that doesn't mean that outcome is so great.
Say that the sub logic to format a user profile link turned out to be needed outside this notification context. Our foresight to have made it reusable in the first place was solid. Now two completely different functional contexts are reusing this logic. Next, the marketing department goes: well actually...you need to add a tracking param specifically for links in the notification context, and only there.
Now your "portability" is a problem. There's various ways to deal with it, and I'm sure we'll pick the most complicated one in the name of some best practice.
After 20 years in the industry, you know how I would write the logic? A single method "formatNotification". It wouldn't weirdly copy the entire object over and over again, it would directly manipulate the object, one piece at a time. Error checking is in the method as well. You can read the entire logic top to bottom without jumping into 7 files. You can safely make changes to it and its intuitive to debug. Any junior would get it in about 2 minutes.
Clear, explicit code that requires minimum cognitive parsing.
You start out with code that will not win any beauty awards but it gets the job done. It's easy to understand by programmers of any seniority, it's simple to debug and reasonably easy to put in an automatic unit test.
Next, you add all kinds of vague, poorly named meta utilities that don't seem to solve any tangible real world problem. You even mess with built-in JS methods like map. The code is now harder to understand and more difficult to debug.
A massive pain is added for some theoretical purity that few even understand or will benefit from. I'll double down on my rebellion by stating that the portability of code is overrated.
Here we're writing code to format notification objects. In our overengineering mindset, we break this down into many pieces and for each piece consider reusability outside this context to be of prime importance.
Why though? Why not just solve the problem directly without these extra self-inflicted goals? The idea that this is a best practice is a disease in our industry.
Most code that is written prematurely as reusable, will in fact never be reused outside its original context. And even if it is reused, that doesn't mean that outcome is so great.
Say that the sub logic to format a user profile link turned out to be needed outside this notification context. Our foresight to have made it reusable in the first place was solid. Now two completely different functional contexts are reusing this logic. Next, the marketing department goes: well actually...you need to add a tracking param specifically for links in the notification context, and only there.
Now your "portability" is a problem. There's various ways to deal with it, and I'm sure we'll pick the most complicated one in the name of some best practice.
After 20 years in the industry, you know how I would write the logic? A single method "formatNotification". It wouldn't weirdly copy the entire object over and over again, it would directly manipulate the object, one piece at a time. Error checking is in the method as well. You can read the entire logic top to bottom without jumping into 7 files. You can safely make changes to it and its intuitive to debug. Any junior would get it in about 2 minutes.
Clear, explicit code that requires minimum cognitive parsing.
"Instead, the most intelligent coders I knew tended to take it up; the people most passionate about writing good code."
Ah, yes, the most intelligent people tended to take it up, therefore if I take it up I, too, am intelligent.
That single line in the article encapsulates everything wrong with FP zealots' approach to their advocacy.
Ah, yes, the most intelligent people tended to take it up, therefore if I take it up I, too, am intelligent.
That single line in the article encapsulates everything wrong with FP zealots' approach to their advocacy.
FP is only part of the equation when working with meaningfully-complex systems. Having a clear data + relational model is the other big part.
I would strongly recommend reviewing the functional-relational programming model described in this paper - http://curtclifton.net/papers/MoseleyMarks06a.pdf
The overall theme goes something like: FP is for handling all your logic, and RP is for arranging all of your data. Some sort of relational programming model is the only way to practically represent a domain with high dimensionality.
For real-world applications, we asked ourselves: "Which programming paradigm already exhibits attributes of both FP and RP?" The most obvious answer we arrived at is SQL. Today, we use SQL as a FRP language for configuring our product. 100% of the domain logic is defined as SQL queries. 100% of the domain data lives in the database. The database is scoped per unit of work/session, so there are strong guarantees of determinism throughout.
Writing domain logic in SQL is paradise. Our tables are intentionally kept small, so we never have to worry about performance & indexing. CTEs and such are encouraged to make queries as human-friendly as possible. Some of our most incredibly complex procedural code areas were replaced with not even 500 characters worth of SQL text that a domain expert can directly understand.
I would strongly recommend reviewing the functional-relational programming model described in this paper - http://curtclifton.net/papers/MoseleyMarks06a.pdf
The overall theme goes something like: FP is for handling all your logic, and RP is for arranging all of your data. Some sort of relational programming model is the only way to practically represent a domain with high dimensionality.
For real-world applications, we asked ourselves: "Which programming paradigm already exhibits attributes of both FP and RP?" The most obvious answer we arrived at is SQL. Today, we use SQL as a FRP language for configuring our product. 100% of the domain logic is defined as SQL queries. 100% of the domain data lives in the database. The database is scoped per unit of work/session, so there are strong guarantees of determinism throughout.
Writing domain logic in SQL is paradise. Our tables are intentionally kept small, so we never have to worry about performance & indexing. CTEs and such are encouraged to make queries as human-friendly as possible. Some of our most incredibly complex procedural code areas were replaced with not even 500 characters worth of SQL text that a domain expert can directly understand.
GOOD: having large chunks of code that runs (mostly) without side-effects. As projects get bigger global state can trip you up, so try to keep it in check. That's where the real value of functional programming is.
BAD: copying data needlessly and turning trivial stuff into a functional pipeline that is impossible to debug. You want your code to read top to bottom like the problem you're trying to solve, if at all possible. If your call stack looks like map, fold, reduce you've introduced a ton of complexity, and why exactly?
Every programmer should understand functional programming. Higher order functions can be super useful. Immutable objects are invaluable for preventing subtle bugs. But if you feel the need to transform simple linear code into a map of higher order functions because of some abstract benefits you're probably doing stuff that's too easy for you and you should get your mental challenge from solving a more difficult problem instead.
BAD: copying data needlessly and turning trivial stuff into a functional pipeline that is impossible to debug. You want your code to read top to bottom like the problem you're trying to solve, if at all possible. If your call stack looks like map, fold, reduce you've introduced a ton of complexity, and why exactly?
Every programmer should understand functional programming. Higher order functions can be super useful. Immutable objects are invaluable for preventing subtle bugs. But if you feel the need to transform simple linear code into a map of higher order functions because of some abstract benefits you're probably doing stuff that's too easy for you and you should get your mental challenge from solving a more difficult problem instead.
I'm a fan of functional programming but I'm pretty sure this post would do a terrible job of convincing anyone to try FP out. There's a very bad pattern of replicating very specific language features and control flow structures just to make them more similar to point-free Haskell, which is not going to win anybody over.
The author begins by replacing a language feature, the . operator, with a pipe() function. After that they swap out exceptions for Result, null/undefined for Maybe, Promise with Task, and the final code ends up becoming an obfuscated mess of wrapper functions and custom control flow for what you could write as:
This post has nothing to do with functional programming, this is a poor monad tutorial.
The author begins by replacing a language feature, the . operator, with a pipe() function. After that they swap out exceptions for Result, null/undefined for Maybe, Promise with Task, and the final code ends up becoming an obfuscated mess of wrapper functions and custom control flow for what you could write as:
fetch(urlForData)
.then(data => data.json())
.then((notifications) =>
notifications.map((notification) => ({
...notification,
readableDate: new Date(notification.date * 1000).toGMTString(),
message: notification.message.replace(/</g, '<'),
sender: `https://example.com/users/${notification.username}`,
source: `https://example.com/${notification.sourceType}/${notification.sourceId}`,
icon: `https://example.com/assets/icons/${notification.sourceType}-small.svg`,
})
)
.catch((err) => { console.log(err); return fallback });
...which is just as functional because doesn't involve any mutation and it doesn't require several pages of wrapper functions to set up, you can tell what it does at a glance without having to look up any other pieces of code, it's gonna run faster, and it uses standard control flow which you can easily debug it using the tools you use for any other JS code.This post has nothing to do with functional programming, this is a poor monad tutorial.
I read the whole thing waiting for the aha-erlebnis which never came. I'm a full stack JS/TS engineer with a decade of experience. I expected this article to be written for someone like me. It didn't click, even though I already love and use functional aspects like immutability and pure functions. I feel like it's the whole new set of terminology that puts me off (and I'm talking about `scan` and `Task`, not even `Functor` or `Monad`). I have confidence I can learn and apply this in a few weeks, but I can't realistically expect junior/medior devs to quickly onboard into a codebase like that.
Maybe I'm biased against "true" functional programming because I've been on Clojure and Scala projects in the past (as a backend dev) and both experiences have been good for my personal/professional development, but a shitshow in terms of long-term project maintenance caused by the enormous learning curve for onboarding devs. The article talks about how great it is for confidently refactoring code (which I bet is true) but doesn't talk about getting people to understand the code in the first place (which is still a requirement before you can do any kind of refactoring).
My only hope is for ECMAScript (or maybe TypeScript) to introduce these OK/Err/Maybe/Task concepts as a language feature, in a way which befits the language rather than trying to be "complete" about it. We don't need the full spectrum of tools, just a handful.
Maybe I'm biased against "true" functional programming because I've been on Clojure and Scala projects in the past (as a backend dev) and both experiences have been good for my personal/professional development, but a shitshow in terms of long-term project maintenance caused by the enormous learning curve for onboarding devs. The article talks about how great it is for confidently refactoring code (which I bet is true) but doesn't talk about getting people to understand the code in the first place (which is still a requirement before you can do any kind of refactoring).
My only hope is for ECMAScript (or maybe TypeScript) to introduce these OK/Err/Maybe/Task concepts as a language feature, in a way which befits the language rather than trying to be "complete" about it. We don't need the full spectrum of tools, just a handful.
It's a bit of a canard.
The benefits of FT are mostly things like statelessness, no side effects.
And it's almost better to talk about it in those terms, and introduce concepts into imperative programming.
When people say 'functional core (aka libs) and imperative for the rest' it's ultimately what they mean.
Applying FP universally creates weird code and it becomes pedantic and ideological.
I wouldn't even use the example in the article almost nothing is gained.
Try to reduce state, use immutable objects as much as possible / where reasonable, make reusable function which naturally have fewer side effects etc..
I think that the material benefit of FP is in partial application of some elements of it, and unfortunately that doesn't create nice academic threads for people to talk about. It's more like applied know-how, than theory.
The benefits of FT are mostly things like statelessness, no side effects.
And it's almost better to talk about it in those terms, and introduce concepts into imperative programming.
When people say 'functional core (aka libs) and imperative for the rest' it's ultimately what they mean.
Applying FP universally creates weird code and it becomes pedantic and ideological.
I wouldn't even use the example in the article almost nothing is gained.
Try to reduce state, use immutable objects as much as possible / where reasonable, make reusable function which naturally have fewer side effects etc..
I think that the material benefit of FP is in partial application of some elements of it, and unfortunately that doesn't create nice academic threads for people to talk about. It's more like applied know-how, than theory.
Before you come at me with pitchforks: I built commercial software with Erlang. I use functional(-style) programming in all languages that support it.
I skimmed through this, and came across this gem:
> If there happens to be an error, we log it and move on. If we needed more complex error handling, we might use other structures.
Yes. Yes, we always need more complex error handling. So, show us the "other structures". It may just turn out to be that the regular chain of `.map` calls with a try/catch around it is easier to understand and significantly more performant than any convoluted pile of abstractions you've built.
And then you'll need to handle different errors differently. And then you'll need to retry some stuff, but not other stuff etc.
> this is a sample chapter from my upcoming book: “A skeptic’s guide to functional programming with JavaScript.”
The problem is: it does a poor job of convincing skeptics why this is great, or even useful. I use, or used to use, functional programming, and I am not convinced by this chapter.
I skimmed through this, and came across this gem:
> If there happens to be an error, we log it and move on. If we needed more complex error handling, we might use other structures.
Yes. Yes, we always need more complex error handling. So, show us the "other structures". It may just turn out to be that the regular chain of `.map` calls with a try/catch around it is easier to understand and significantly more performant than any convoluted pile of abstractions you've built.
And then you'll need to handle different errors differently. And then you'll need to retry some stuff, but not other stuff etc.
> this is a sample chapter from my upcoming book: “A skeptic’s guide to functional programming with JavaScript.”
The problem is: it does a poor job of convincing skeptics why this is great, or even useful. I use, or used to use, functional programming, and I am not convinced by this chapter.
I really dislike when programming books are overly terse with their code examples. This is a problem I've struggled with since I was a child learning to code.
When I'm learning a new concept, I need to be able to clearly see the steps. Even if I do understand how to read and write in the abbreviated coding style, the extra step of mentally decoding it into it's more verbose form takes mental energy away from the absorption of new knowledge.
Clearly, this book is written for an advanced audience, but at the same time it's trying to teach an unfamiliar concept to that advanced audience.
Does anyone else here share my sentiment?
It makes me think of this software I saw once that would take a math-problem, and solve it for you, showing you the steps along the way to the solution. I want something like that for this kind of code.
When I'm learning a new concept, I need to be able to clearly see the steps. Even if I do understand how to read and write in the abbreviated coding style, the extra step of mentally decoding it into it's more verbose form takes mental energy away from the absorption of new knowledge.
Clearly, this book is written for an advanced audience, but at the same time it's trying to teach an unfamiliar concept to that advanced audience.
Does anyone else here share my sentiment?
It makes me think of this software I saw once that would take a math-problem, and solve it for you, showing you the steps along the way to the solution. I want something like that for this kind of code.
`sanitizeMessage` is literally just `message.replace(/</g, '<')` but it has to go through a ton of abstractive scaffolding just so that it can fit into a single call to map(). This is like jumping through a ton of generic classes in Java only to find a single one-liner implementation at the end of the call.
Every FP advocate I know comes from an imperative/OOP background… None of them are juniors. None of the “FP skeptics” (or people parroting an obvious variant of uninformative “right tool for the job”) I know come from an FP background.
People only seem to convert one way and not the other. And is it really a surprise that the vast majority of people resist change / doing things differently?
People only seem to convert one way and not the other. And is it really a surprise that the vast majority of people resist change / doing things differently?
Its greatest strength I see is its simplicity. OOP gives a lot of latitude to overcomplicate solutions, and I've found it tends to obscure more obvious solutions to certain problems, e.g. reaching for inheritance to modify behaviours instead doing it by passing functions as arguments, especially among less experienced team members.
The biggest problem in software development is the slow down of value output over time caused by accumulating complexity. Anything that can help keep complexity down is a big win for long term value output.
The biggest problem in software development is the slow down of value output over time caused by accumulating complexity. Anything that can help keep complexity down is a big win for long term value output.
When it comes to programming, pretty much everything boils down to two key elements:
Each of those paradigms - and many others - are just tools in our arsenal to achieve our goals, and neither is intrinsically better than the other. Depending on the context and environment that we are operating within, each has its advantages and disadvantages; some are better suited than others in certain cases.
- Some kind of data/information, in some (digital) form of one structure or another.
- Methods, processes and operations that transform, transport and do other things to that data.
For example, in OOP, those two elements are generally combined together in organisational units ("objects"); on the other hand, in functional programming they are strictly separated.Each of those paradigms - and many others - are just tools in our arsenal to achieve our goals, and neither is intrinsically better than the other. Depending on the context and environment that we are operating within, each has its advantages and disadvantages; some are better suited than others in certain cases.
(Off topic comment) With the font you're using to write code it's sometimes difficult to read some of the characters. For instance, I had some problems to read the `getKey` method, since the `K` char is pretty blurred.
After reading this article, I changed my mind about functional programming. I no longer think I need to learn it asap. I now think it may actually make my code more difficult to understand and maintain, and will keep avoiding such patterns.
Unfortunately, it didn't help to convince me either.
For me the question still remains: how is any of this better than good ol' reliable `for` loop?
For me the question still remains: how is any of this better than good ol' reliable `for` loop?
If you start with a program, see it as a block of logic that can be separated into parts with cuts in many different places. Choose the cuts so as to leave it a composition of functional programming abstractions. Then it is easy to reason about and it is possible to teach others to code in the same way. This is a benefit for functional programming - a promise of consistency in thought and style that is easy to debug.
The argument I read in this article seems to be going in that direction, but I'm not sure it is being presented clearly. The semi-monoid functors are a fair way down in the weeds and not really what people should focus on when deciding why functional programming is great. Unless they really like abstractions in which case more power to them.
The argument I read in this article seems to be going in that direction, but I'm not sure it is being presented clearly. The semi-monoid functors are a fair way down in the weeds and not really what people should focus on when deciding why functional programming is great. Unless they really like abstractions in which case more power to them.
Why so much indirection and abstraction when it can be done more simply and directly?
const newData = notificationData.map(ev => {
return {
username : ev.username,
message : ev.message.replace(/</g, '<'),
date : new Date(ev.date * 1000).toGMTString(),
displayName: ev.displayName,
sender : `https://example.com/users/${ev.username}`,
source : `https://example.com/${ev.sourceType}/${ev.sourceId}`,
icon : `${iconPrefix}${ev.sourceType}${iconSuffix}`
}
});i will say one thing about functional programming. it does feel amazing to write all those stateless functions and using all kinds of operators.
here is where one gets into trouble, reading functional code. while it may look better when you write it, try reading your own code after a few weeks. you will appreciate it much more when your control flow in a significantly large enterprise application is through bunch of ifs and imperative loops than scattered across various functions and operators.
another problem, debugging. when your inputs cross various function boundaries, no matter how smart IDEs you have, you end up messing around adding impurities to your pure functions and adding watches with conditions all over the place.
lastly, all that lux code does hide a significant problem. Performance. I don't know about javascript but all those temporary objects one keeps creating for the pursuit of statelessness is maddening. i don't know if there is anything characteristically different about a language like Haskell which handles this problem. Does it end up creating new objects every time for e.g. a map is called like in this example to update all the attributes?
here is where one gets into trouble, reading functional code. while it may look better when you write it, try reading your own code after a few weeks. you will appreciate it much more when your control flow in a significantly large enterprise application is through bunch of ifs and imperative loops than scattered across various functions and operators.
another problem, debugging. when your inputs cross various function boundaries, no matter how smart IDEs you have, you end up messing around adding impurities to your pure functions and adding watches with conditions all over the place.
lastly, all that lux code does hide a significant problem. Performance. I don't know about javascript but all those temporary objects one keeps creating for the pursuit of statelessness is maddening. i don't know if there is anything characteristically different about a language like Haskell which handles this problem. Does it end up creating new objects every time for e.g. a map is called like in this example to update all the attributes?
I didn't understand what was the point of the introduction with so many words like that.
Author describes functional programming zealots and seems to imply it's all annoying because of all the abstractions, then proceeds to do exactly that while calling it "the good parts".
Author describes functional programming zealots and seems to imply it's all annoying because of all the abstractions, then proceeds to do exactly that while calling it "the good parts".
The first code iteration in this article could have been deployed to Production before I finished reading the rest of the article.
Functional programming definitely has its use cases, as side effects can introduce bugs. Unfortunately real world business logics often does require side effects. Often you only find out about side effects later in a project, and then you suddenly need to start hacking your clean functional approach.
Functional programming definitely has its use cases, as side effects can introduce bugs. Unfortunately real world business logics often does require side effects. Often you only find out about side effects later in a project, and then you suddenly need to start hacking your clean functional approach.
I am a fan of mixing functional and object oriented (and also some other paradigms).
Functional is great in cutting amount of repeatable code. It is great for writing tools to process things regardless of their exact type and for writing infrastructure code.
Object orientation is great when you want to model the domain of the problem. Things that actually make sense when you are talking to non-developers at your company. Clients, contracts, appointments, employees, teams, invoices, things like that. But when you start making objects that do not represent anything meaningful you probably went a bit too far.
I think knowing various paradigms, knowing when to use which and how to marry them together is critical for maintainable implementations.
Functional is great in cutting amount of repeatable code. It is great for writing tools to process things regardless of their exact type and for writing infrastructure code.
Object orientation is great when you want to model the domain of the problem. Things that actually make sense when you are talking to non-developers at your company. Clients, contracts, appointments, employees, teams, invoices, things like that. But when you start making objects that do not represent anything meaningful you probably went a bit too far.
I think knowing various paradigms, knowing when to use which and how to marry them together is critical for maintainable implementations.
Yeah. I'm one of those who are not convinced yet about functional programming being so great. In most cases what people call functional programming are inefficient shortcuts to lengthier functions, so I never got all that hype about it :\
The other day I watched a self-described functional programmer implement a while loop using this custom-written conditionally recursive function.
There was nothing more elegant about it and it wasn't obvious from just looking at the function call what the function was doing. It wasn't any simpler than while(condition){}.
All because he didn't like while loops (and statements in general). It seemed tortuous and unnatural.
FP has some good parts but so does imperative programming, and I think throwing away the good parts of imperative programming and OOP for the sake of "pure" FP is a serious mistake.
There was nothing more elegant about it and it wasn't obvious from just looking at the function call what the function was doing. It wasn't any simpler than while(condition){}.
All because he didn't like while loops (and statements in general). It seemed tortuous and unnatural.
FP has some good parts but so does imperative programming, and I think throwing away the good parts of imperative programming and OOP for the sake of "pure" FP is a serious mistake.
> One of the people I showed this to had an interesting reaction. Their response was something like: “Hey! I like functional programming because I’m lazy and incompetent. It’s about all the things I don’t have to think about.”
I can perfectly imagine the most intelligent and smart people I've ever meet saying this same thing.
I can perfectly imagine the most intelligent and smart people I've ever meet saying this same thing.
Just a quick heads-up, if you want to truly write functional code in the browser there is js_of_ocaml available in the OCaml realm. With Bonsai [0] a somewhat usable framework for webapps is available now, too. There are drawbacks like filesize, but if you don't have to serve the webapp on the first pageload it shouldn't be a problem.
[0]: https://bonsai.red
[0]: https://bonsai.red
The venerable master Qc Na was walking with his student, Anton. Hoping to prompt the master into a discussion, Anton said "Master, I have heard that objects are a very good thing - is this true?" Qc Na looked pityingly at his student and replied, "Foolish pupil - objects are merely a poor man's closures."
Chastised, Anton took his leave from his master and returned to his cell, intent on studying closures. He carefully read the entire "Lambda: The Ultimate..." series of papers and its cousins, and implemented a small Scheme interpreter with a closure-based object system. He learned much, and looked forward to informing his master of his progress.
On his next walk with Qc Na, Anton attempted to impress his master by saying "Master, I have diligently studied the matter, and now understand that objects are truly a poor man's closures." Qc Na responded by hitting Anton with his stick, saying "When will you learn? Closures are a poor man's object." At that moment, Anton became enlightened.
- Anton van Straaten
Chastised, Anton took his leave from his master and returned to his cell, intent on studying closures. He carefully read the entire "Lambda: The Ultimate..." series of papers and its cousins, and implemented a small Scheme interpreter with a closure-based object system. He learned much, and looked forward to informing his master of his progress.
On his next walk with Qc Na, Anton attempted to impress his master by saying "Master, I have diligently studied the matter, and now understand that objects are truly a poor man's closures." Qc Na responded by hitting Anton with his stick, saying "When will you learn? Closures are a poor man's object." At that moment, Anton became enlightened.
- Anton van Straaten
> What we care about is “can we deliver better code, faster“
Strawman! Most coders, even staunchly “imperative” ones care a lot about tech debt, tidyness and code quality. That is why things like SOLID and design patterns are popular. For better or worse good programmers are proud of their code, and I don’t meet too many who feel they need to “ship faster”. Product people might want that though.
Strawman! Most coders, even staunchly “imperative” ones care a lot about tech debt, tidyness and code quality. That is why things like SOLID and design patterns are popular. For better or worse good programmers are proud of their code, and I don’t meet too many who feel they need to “ship faster”. Product people might want that though.
The pipe feels like a block of restricted statements, `peekErr` and `scan` recreate conditionals, the Maybe monad behaves like a try-catch here, etc.
Of course there are differences, like `map` working on both lists and tasks, as opposed to a naive iteration. That's cool. But this new programming language comes with limitations, like the difficulty in peeking ahead or behind during the list iteration, reusing data between passes, and not to mention the lost tooling, like stack traces and breakpoints.
I've written many (toy) programming languages, the process is exactly like this article. And it feels awesome. But I question the wisdom of presenting all this abstract scaffolding as a viable Javascript solution, as opposed to a Javascripter's introduction to Haskell or Clojure, where this scaffolding is the language.