27 ms·
What’s so great about functional programming anyway?
- mcv 4y ago> Functional programming is all about having confidence in our code. Perhaps, but if I understand this article correctly, I must first know and understand all these laws and tools before I can have that confidence. Meanwhile, the arcane abstractions don't exactly inspire much of that confidence. Look, I love what someone else here has already dubbed "softcore FP". I love chaining functions that pass immutable data structures to each other. And I fully admit I've written some highly abstract code that looks quite a bit like some of this. But does it inspire confidence? Quite often the effect is that you've created your own language that others don't know, which means your code will be harder to understand for others, and they may lack confidence in the code, and not dare to maintain it properly. I want to believe that this direction is the right one, but I lack the confidence that it really is.
- evaneus 4y agoJust want to point out that (as of 16:44 UTC 17th Nov) there are 52,268 words on this page. So far no-one has called anyone a Nazi. It's fascinating and good that people care about this stuff. Software engineering would be very boring if there wasn't room for opinion. My opinion is that if you were to summarize the original article to only one of its words, it would be the lovely word "boffin". The right amount of boffinry can be a rewarding and beautiful thing. Sometimes though "C'est magnifique mais ce n'est pas la guerre".
- mohitgangrade 4y agoI write JavaScript all day long for my personal projects and my clients. But functional programming, at least as I see in this article, looks like a lot of extra work to do something simple. I am sure I'm missing something here. But I don't understand why I would ever need to use code like this. My clients and I value shipping code as fast as possible. This just looks like it would turn my 1 hour job into 2 hours with not much benefit. Anyone who doesn't have a lot of experience with JavaScript or functional programming will have a really hard time reading and understanding my code. I've been coding for a long time now in JavaScript but this looks like a lot of complex code to me for simple tasks. I want to love functional programming because everyone is talking about it. But what am I missing? What would be the benefit of recreating a language inside a language?
- deleted 4y ago[deleted]
- dna_polymerase 4y agoJust 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 https://bonsai.red
- davidgl 4y agoOr https://fable.io https://fable.io in the F# world, which is production ready and excellent
- throwaway0asd 4y agoI am not a zealot as the book might describe. My personal goals are portability and predictability of code. Use of functions with defined return types in TypeScript, as opposed to other containers by reference, allow me to achieve those goals. Most of my functions though are void functions (returning null or undefined). It’s not essential to me that functions must return a value, in defiance to functional programming, so long as like instructions are grouped in a single container that may be called by reference.
- dmitriid 4y agoBefore 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.
- wruza 4y agoshow us the "other structures" “Left as an exercise to the reader”. Reminds me those well-known tutorials with todo lists and other trivial nonsense, because a fully-fledged example would seed doubt of selling points instantly. Sometimes I think that our area is one big IKEA store. You look at nice pictures, buy into the crap, and still feel okay because you’ve built most of it yourself. Not getting that this built-yourself part makes you relate to it much more than the initial advertisement or the practical value.
- dmitriid 4y ago> “Left as an exercise to the reader”. Or "draw the rest of the owl" :)
- alexmolas 4y ago> 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.
- googlryas 4y agoMaybe a key part of intelligence is merely knowing your own limitations.
- masklinn 4y agoOr offloading so you have more room for the useful stuff.
- EnKopVand 4y agoThere is a Danish scientist called Morten Münster who's done research on behavioural science. He's written a book for management that's gotten very popular in my country, and this is how I became acquainted with it back when I did a stint in management (which around here includes getting a MBA type education in management). Aaaaaaaanyway, in it he talks about two ways of how we function as human beings, and I'm likely presenting this wrong, but one is basically the best practice theoretical mode of being and the other is how we operate at 17:00 on a Thursday after a week where both our children have been sick, and the overlaying message is that everything that isn't designed for the second mode of being is likely going to fail. Now the way it's presented in the research and the educational material, this has nothing to do with programming. It's more along the lines of companies needing to formulate missions and goals that aren't corporate bullshit, because nobody understands corporate bullshit when they are faced with an angry customer some late Thursday afternoon. After a few decades in SWE, however, I've become sort of a fan of designing software for that 17:00 Thursday EnKopVand mindset, and functional programming helps a lot in that regard because it kills soooo many of the complexity pitfalls that you really don't want to deal with when you're tired, lazy and incompetent. Of course the other side of this is that I'm not religious about functional programming either, I rarely write classes these days, but if there is a good reason to write one, I will.
- alexmolas 4y ago(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.
- rob74 4y agoIt's supposed to look like an old typewriter with partly broken types, but it looks like they overdid it on the "K"... plus no typewriter I know of can write with light color on a dark background, so that kind of breaks the illusion.
- joshcrowder 4y agoI came to write the same thing. Fine for reading text, not ideal for code
- epse 4y agoThe K character is completely invisible on my machine even
- gizmo 4y agoGOOD: 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.
- mejutoco 4y agoAgree, especially with having as much part of the code as pure functions. I think where functional programming really shines is in combination with a good type system, that can enforce those restrictions. In languages like js I find it not so useful (even if using map, filter, etc.) because I have no guarantees that there is a hack somewhere in the function that I did not see. When there are a lot of pure functions the cognitive load is reduced so much I can use the "extra capacity" to focus on the task.
- gizmo 4y agoIn Javascript Object.freeze() and Object.seal() are wonderful to prevent accidental mutation.
- mejutoco 4y agoI did not know that. Another one is const to declare simple variables. There are some features, I agree. But how do I declare that a function returns a specific type and have it enforced? IMO, only by switching to Typescript or similar.
- piyush_soni 4y agoYeah. 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 :\
- spoiler 4y agoThe nice thing about functional programming is that it allows you to shift some of the "mundane" domain thinking onto the type system. A classical example of that might be to mix units in physics code. So, nonsenses like adding up lengths and time is no longer possible. Things also generally compose together more easily than in OO. There's other benefits too, but these are my main ones. So, once you set up this invariant groundwork, you free your mind from thinking about certain problems, as the compiler catches them for you. This isn't to say these things can't be done in OO (they have been done), but they're usually not enforced to the same level, as it's normally a library, not native functionality
- tsimionescu 4y agoThe benefits of type systems are either entirely orthogonal or at best are themselves a prerequisite for the benefits of FP. Your example of measurement units in particular is applicable to the most imperative goto laden code we could think of. In fact, some of the more popular functional languages are untyped - those being Clojure, Erlang and Scheme.
- piyush_soni 4y agoExactly my point, I'm sure there are benefits, but this example is more suited to Typed languages whereas many functional languages like you say are untyped. And man, I've worked with MIT Scheme in a major commercial software for 5+ years. What a nightmare it was. :(. I mostly understood the functional aspect of the language, but the sea of misplaced brackets and a complete lack of any debugger (at least for our version of it) whatsoever made it one of the worst languages to work with. The biggest irony was, since Scheme is apparently so extensible, they had created a home-grown "Object Oriented Scheme", which implemented only some aspects of OOP and omitted some other very important ones, and it was upto the developer to find out the hard way which ones were omitted! :D
- Jorengarenar 4y agoUnfortunately, 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?
- mrkeen 4y agoHow is the for-loop any better than good ol' GOTO?
- Jorengarenar 4y agoConceptually, `for` loop is just syntactic sugar - it simplifies certain action, not makes it more difficult.
- pedrovhb 4y agoConceptually, the `map` function is just syntactic sugar for `for` loops, and it's also meant to simplify actions. There are functional equivalents to many small patterns of code that occur often - for instance lst = [] for element in range(10): lst.append(element * 2) Is a very common pattern, that can be expressed with less typing (and less mental overhead, when you become used to it) by lst = list(map(lambda x: x * 2, range(10))) Similarly, another very common mini-pattern is total = 0 for el in range(10): total += 3 * el Which can be more swiftly expressed by total = reduce(lambda acc, el: acc + 3 * el, range(10)) These examples are trivial, but once you start using these higher level syntactic sugar-like constructs, you often find that code tends to fit together more nicely and in ways that make more sense, even if only because you used a filter operation before the map instead of writing another level of nested `if` statements inside a loop body. Code gets easier to follow, not unlike how it's easier to reason about the behavior of a `for` loop than it is to keep a bunch of `goto`s in your mental model of what the code does while at the same time thinking about whether the business logic part of it makes sense.
- im3w1l 4y agoFor what its worth, the pythonic solution is lst = [x * 2 for x in range(10)]
- jalapenos 4y agoIts 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.
- kalekold 4y agoIf OOP is over-complicating your code, you're using it wrong. OOP is a tool to manage complexity. Functional programming, in my experience, created much more complicated code because it seems like the authors like to be a clever as possible.
- jalapenos 4y agoOnce you zoom out to the bigger picture of dozens of devs writing the code rather than yourself, its more a matter of "statistically, if I recommend functional over OOP, how simple will the code be a year from now". But granted it needs to be part of a broader pressure to keep things simple, otherwise devs will like you say, find a way to overcomplicate.
- epgui 4y agoAre you confusing "complicated" with "unfamiliar"?
- prmph 4y agoIndeed. Although I have mostly stopped using OOP in most of my code, I sometimes encounter certain classes of problems that are exceedingly complicated to solve in a purely functional way, but that are a breeze to solve using OOP, believe it or not. One can mix functional and OOP code well by compartmentalizing the parts of the code that are in OOP style, and situating it in an overall functional context. For example, the methods of a class can certainly be written in a very functional style, and classes themselves can be instantiated within functions. The mark of a skilled developer is to know which paradigm is the best to solve a particular problem, just like the choice of a data structure can greatly affect simplicity of code to address a problem.
- gtirloni 4y agoI 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".
- roenxi 4y agoIf 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.
- commitpizza 4y agoInteresting article with an interesting writing style, I may pick up the book even if I suck at reading books! I didn't start as a skeptic and really think functional programming looks beautiful and is very useful in preventing side effects. However, in most practical situations I've found over the years functional programming to be harder to understand and debug when stuff goes wrong. In javascript in particular, functional programming is very nice but at the same time usually way more ineffecient so for many tasks I tend to go back to normal for loops just because it's that much faster. I had a collegue that wrote a lot of functional code and his code was extremely hard to follow and understand. Even if it was beautiful figuring out where the system went was the hard part and I had to go to the function decleration, understand it, move on to the next until I found whatever the issue was. When I found the issue, I couldn't easily fix it because the next function called was expecting the data structure to behave in a specific way so for one issue once I had to change basically every function called before and after which was way more tedious then if it would have been more sequential. I don't know. There is something to say about functional programming but lately I have kind of tilted back into the more standard approach. Functional programming is a lot more beautiful in practically every implementation I've seen but the standard approach is, in my experience, usually more useful in practical terms.
- zozbot234 4y ago> I had a collegue that wrote a lot of functional code and his code was extremely hard to follow and understand. That's not a problem with functional code, it's about badly designed abstractions. You get the same issues in garden-variety OOP codebases, only to a far greater extent.
- oxfordmale 4y agoThe 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.
- mrkeen 4y ago> side effects can introduce bugs > real world business logics often does require side effects > you suddenly need to start hacking your clean functional approach These are great arguments as to why you need: a) A type system which tracks effects b) A language which makes refactoring safe and easy
- z9znz 4y ago> real world business logics often does require side effects Yeah, all business logic requires side effects, else it is doing nothing :). But following some FP practices, you can push the side effects very far out to ward the edges. Instead of typical OOP, where objects get passed around and mutated anywhere and everywhere (which makes identifying where certain things started to go wrong), with pure, single responsibility functions you can write very simple but thorough tests which give you vastly more confidence about the code. And as a huge added benefit, the lines of test code actually go down because there's so much less setup and teardown (mocking, stubbing, etc.).
- gehen88 4y agoI 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.
- zmmmmm 4y agoAlways makes me sad that Scala got sucked into the pure-functional priesthood type culture rather than the "better Java, by being mostly functional and immutable and then practical as hell when appropriate" pathway. I really like coding using Scala but the way I like to do it feels totally non-idiomatic.
- piaste 4y ago> "better Java, by being mostly functional and immutable and then practical as hell when appropriate" That's very much what Kotlin is aiming for.
- gehen88 4y agoSo true. I was involved in two very different Scala projects. One was the sensible "better Java" way, which was mostly great. The other was a big enterprise project with a core group of "hardcore" FP enthusiasts which was very stressful because of imposter syndrome and troubles to onboard new folks. I have been against Scala ever since, exactly because of this FP cult.
- SPBS 4y ago`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.
- z9znz 4y agoI believe that his example for sanitizeMessage() was just to give an example. An actual sanitizer would be much more complex, and thus having a separate function defined to do that one thing would be more obviously reasonable. But you DO want these single responsibility methods like sanitizeMessage()! Having single responsibility functions like this means you have more Legos you can use where you need. You get improved code reuse. Perhaps more importantly, you also get functions which are easy to test and test more thoroughly than if you have a big procedure which does a lot of things.
- DavidSharff 4y agoWhile there are areas where my functional convictions have greatly diminished, my mid career zeal had the tremendous benefit of illuminating new architecture and data design principles. Storing data as discreet changes and relying on pure function selectors to calculate values is wonderful. It's not always a viable approach at scale (at least not for my ability in certain circumstances) but, when it is, testing is a breeze and I love being able to debug forward/backward in time with consistent results guaranteed.
- nonrandomstring 4y ago> (great? (programming(functional))) (allows (ideas (elegantly(expressed))))
- ludston 4y ago(-> except appropriate use of macros makes it easier to both write and read)
- epgui 4y agoEvery 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?
- JackFr 4y agoI was 3 years hardcore Scala, but recently went back to Java for a role. I didn't really find returning to Java to be an encumbrance at all, and really enjoyed how productive Spring Boot made me. I still love Scala and if you don't fight it and use it long enough, the crazy sounding FP/category theory stuff starts to come up naturally and seem very comprehensible. My takeaway is always avoid known bad practices, but otherwise to cut with the grain. Write Java like Java, JavaScript like JavaScript and Scala like Scala.
- mrkeen 4y agoHear, hear. When I program, I like to use: { functions, types } When FP gets bolted onto a mainstream language after the fact, you get to program with: { classes, mutability, side-effects, nulls, functions, types } Then the FP skeptics think it's too complicated, and just want to go back to: { classes, mutability, side-effects, nulls }
- epgui 4y agoWhy not just use COBOL and Gotos while we’re at it? It was “the right tool for the job” for decades until the OOP religion took over! /in_jest
- mrkeen 4y agoSure /s. But seriously I dislike the notion that FP is somehow a successor to OOP, like you have to keep piling abstractions onto OOP until it becomes FP! If you do it that way, you end up with map() implementations like: public final <R> Stream<R> map(final Function<? super P_OUT, ? extends R> mapper) { Objects.requireNonNull(mapper); return new StatelessOp<P_OUT, R>(this, StreamShape.REFERENCE, StreamOpFlag.NOT_SORTED | StreamOpFlag.NOT_DISTINCT) { Sink<P_OUT> opWrapSink(int flags, Sink<R> sink) { return new Sink.ChainedReference<P_OUT, R>(sink) { public void accept(P_OUT u) { this.downstream.accept(mapper.apply(u)); } }; } }; } Ain't nobody got time to read that. Step back from OOP before putting in the FP and you can get map() looking like: map _ [] = [] map f (x:xs) = f x : map f xs
- quickthrower2 4y ago> 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.
- kyberias 4y agoPlease fix the font used for code examples. Unreadable.
- quickthrower2 4y agoThe dirty secret is Typescript is going to become the most popular language due to it’s dirty pragmatism and simultaneously very elegant features. It is definitely a get shit done language. Typescript without JS toolchains (for example compiled to WASM would make it very good).
- RadixDLT 4y agowrite more robust, maintainable code
- Throwaway23459 4y agoThere's no agreed way to organise a functional codebase. You end up with thousands of functions, can you imagine the mess a big team is capable creating? With some discipline I suppose it could work, but you would need some organising principle and some serious discipline. Object oriented is organised by virtue of the object paradigm.
- tempodox 4y agoThe languages in the ML family have modules. They are the agreed-upon way to organize code and control visibility in those languages.
- piaste 4y ago> Object oriented is organised by virtue of the object paradigm. Or in other words, OO code ties business logic to presentation logic. By sticking to the dominant 'one class per file' principle, the same code behaves differently based only on whether it appears in one file or two, so it's not trivial to move code around to make it more organized. When I write functional code, I first write all the functions and types I need in a single file, without worrying about presentation or naming until it compiles. Then, before committing, I reorganize them into folders, files, and modules so it's easier to read and navigate, and I can do it any way is more appropriate (sometimes layer-first is more readable, sometimes domain-first). I can also split pure functions into chains of smaller, pure, private functions if they're too long to follow (90% of the time some functions end up being way longer than I expected), which is _way_ simpler than splitting a large class into smaller ones.
- dluan 4y agoNice writing style!
- dluan 4y agoAlso the markup font is a little wonky and `Ok` ends up looking like `0`.
- z9znz 4y agoFollowing TFA example, I think there's one more step that could be done (or could have been done earlier in the processes) - shift from piped, hardcoded function calls to a data structure which describes the transformations you would like to have applied to your data. With just a few lines of mini-framework definition code, you can define a Processor system which behaves like a pipe+reducer but takes a simple data structure of initial value, functions to call with that data (and optional additional params), with the result of each step fed to the next. But in the framework you take the output of the previous step and update the results key within a process hash. Or if the function fails, you can accumulate errors in an errors key-value pair. Steps can have flags, such as :hard-fail, etc. which the Processor can use to affect special behaviors (like a rollback or a termination) based on errors in steps. This enables really dynamic programming options as the transformations to be done on the data can be determined at runtime based on formulas or process generators. It might seem that such an approach would make debugging and troubleshooting more difficult, but because you can add additional metadata and debug behaviors to the Processor steps data, tracing exactly what has occurred in very easy. The only downside I've found from this approach is that IDEs may not "see" your call to functions as they are just references or strings/symbols (depending on the language).
- revskill 4y agoInstead of const x = await promise1(someArgs); const y = await promise2(someFunction(x)); we do function processor(monad, args) { return monad.unit(promise1(args)).map(someFunction).then(promise2) } That's all about monad.
- jasmer 4y agoIt'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.
- canadianfella 4y agoWhat do you mean by “canard”?
- zabzonk 4y agofalse report
- fleddr 4y agoI'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.
- oldboyFX 4y agoThank you for writing this. I've come to exactly the same conclusion after a decade of building and delivering complex tangible applications which others have to maintain after I'm gone.
- Cort3z 4y agoAs far as I can tell, with this async approach you lose what I consider to be one of the main benefits of the native async functions; If an error is thrown, it will show up in the "reject" path of your promise. This is very useful and is great at preventing "random code" in some Task from causing havoc. I'm not that great at functional programming, and perhaps this is a non-issue, but I feel there could be some way to achieve the same results without losing that ability.
- steinuil 4y agoI'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: 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.
- Kerrick 4y agoYour response describes exactly how I felt using RxJS for the first time.
- dmitriid 4y agoIt took the author of RxJava months to understand the concept. Screenshot from the book: https://twitter.com/dmitriid/status/811561007504093184 https://twitter.com/dmitriid/status/811561007504093184 (Jafar is the author of Rx .Net, and even he couldn't explain it to the future author of RxJava :) )
- dtech 4y ago
- zelphirkalt 4y agoOne thing FP, learned with a suitable language at hand, teaches is, how often we unnecessarily reach for classes, when simple pure functions will do just fine and will be better testable, easier to understand, more reusable, and more composable.
- BoppreH 4y agoI love softcore FP (immutability, first-class functions, etc), but I always get the impression that hardcore FP, like in this article, is about reimplementing programming language concepts on top of the actual programming language used. 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.
- michaelcampbell 4y ago> I love softcore FP (immutability, first-class functions, etc), I couldn't come up with a succinct way to say exactly this, since this is very much how I am with it right now. Thanks for that. I will add I'm comfortable with, and prefer, map/select/reduce over for loops where provided.
- philihp 4y agoI've found this too. Once I got comfortable with map/reduce/filter in JS, the thought of using an imperative while or for loop feels as backwards as writing a goto/label.
- bongobingo1 4y agoThe only thing stopping Functional Programming from taking off are functional programmers. It took me years (and Elixir) to get past the "here are some words, some mean what you think, some mean something completely different to what you know, some mean almost the same thing. Also here's 30 overloaded operators that you have to juggle in your head and we wont introduce things like variables for another 4 pages." without running back to something imperative to actually build something. Functional programming's great when you have immutability to drop an entire class of bugs and the mental energy that accompanies that, can pass-around and compose-with small functions easily which makes writing, testing and figuring much simpler and can make your brain click that "its all data" without trying to over complicate it by attaching methods to it. Honestly I think that's 90% of what the royal You needs to understand to get FP and actually try it. Selling people on "its all stateless man" or other ivory tower tripe is such garbage because (as the tutorials always point out) a program with no state is useless, and then the poor shmuck has to learn about monads just to add a key to a map and print something at which point they're asking "how was this better again?"
- zigzag312 4y agoImproved type system to me is the most valuable. Compared to OO inheritance fest, designing with types popular in functional languages can be much more natural and easier to maintain. There are other valuable things, but IMHO the key is that, like OO programming, they are valuable sometimes, not always. Being explicit what is mutable and what can produces side effects is really good, but forcing everything to be immutable and without side effects, is not. So, while I like some things about functional programming, I'm not a fan of pure functional programming. I'd rather have a language that supports mixing multiple paradigms, even though that means giving up some things that are avaliable only in pure functional languages.
- mrkeen 4y ago> I'm not a fan of pure functional programming > Being explicit what is mutable and what can produces side effects is really good !!! That's what Haskell is !!! What language are you using which is explicit about side effects?
- zigzag312 4y ago> !!! That's what Haskell is !!! I haven't tried Haskell yet. Only F# (of the functional bunch). From what I heard about Haskell, I'm not sure it's what I'm looking for. It sure has functional side covered, but not much else. To me functional programming is based on logic. However, every program runs on a machine, and sometimes it's important to reason what the machine is doing. Focusing just on the logic is not enough every so often. > What language are you using which is explicit about side effects? Sadly, none that I use.
- eurasiantiger 4y agoIn my opinion, FP is one tool in the toolkit, and is best suited for expressing math-oriented things such as set operations, analytics pipelines, and other kinds of data transformations. For any kind of I/O, though, FP is not even applicable in the pure sense of a function, as disk/network access is inherently a side effect. JS can of course mask much of this with its Promises. Any kind of business-oriented logic, especially handling of different kinds of data entities, is still good to encapsulate in classes in OOP fashion. Classes are a good impedance match for entity types, as instances are to entities. Sometimes, though, data transformations are still more clearly expressed in imperative style. At the very least they’re more accessible to juniors, unlike the innards of declarative transformation engines. Imperative, declarative, object-oriented, functional — these are all tools for different jobs.
- valenterry 4y agoPure FP is most useful for IO. Without IO, the concept of pure FP doesn't make any sense.
- eurasiantiger 4y agoThat doesn’t make sense. Any function doing I/O is not pure by definition, and while using an IO monad can shift the impureness a bit to make a function behave as if it was pure, it is not pure and cannot ever be pure. Can you explain?
- valenterry 4y agoYeah - I think from your explanation I can only deduce that you don't know the actual definition and concept of pure functional programming. Note that the term "functional programming" has been watered down over time and now pretty much means "use .map and .filter instead of a loop" etc. Historically the meaning was different though, see: https://en.wikipedia.org/wiki/Purely_functional_programming https://en.wikipedia.org/wiki/Purely_functional_programming With pure functional programming you essentially treat IO-effects as a first class concept and make them explicit in your code. You never "execute" IO directly but compose small "blueprints" for doing IO into bigger blueprints and so on until you end up with one big blueprint which is your application. You then pass it to the runtime ("main() { ...; return bigBlueprint; }") and then it gets executed. In other words, pure functional programming treats IO as more important compared to "regular programming" and without any IO there would be no need to even do so. But without any IO, a program wouldn't have any meaning, because you want at least expose the result of a computation to the outside world.
- allenleee 4y agoFor example, Haskell is optimized for developer efficiency. You can get a lot done, have a high degree of confidence that it runs reasonably without having to do too much thinking or ass-covering. We move fast & need things to be reliable. Rather than hand optimizing Doom 2 for ___.
- koonsolo 4y agoThis post actually confirmed my opinion about functional programming :D. Probably not in the way the author intended.
- waltbosz 4y agoI 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.
- aeonik 4y agoI completely agree with you. This was the main thing slowing me down when I started to learn Clojure last year. I'm now learning Emacs and and Elisp and I find the documentation even more difficult to comprehend somehow. Two examples: Literate programming with org-babel: almost none of the documentation that I can find shows "real" examples with multiple header properties or variables being set for an org-babel file. I don't know how to mix and match them. The docs tend to show the most minimal example and I've been spinning my wheels for days trying to figure out how to integrate into my workflow. Another elisp example: using auth-sources.el for handling credentials. I'm trying to enhance a few major modes to add support for storing server credentials, and none of the examples show how to actually prompt a user for a username and password to save it for later in the secure key store. I've checked other projects, and people do it in different ways, and they all seem needlessly complicated, with core auth logic embedded directly in unrelated function calls. Compare this: https://www.gnu.org/software/emacs/manual/html_mono/auth.html https://www.gnu.org/software/emacs/manual/html_mono/auth.htm... To this: https://pypi.org/project/keyring/ https://pypi.org/project/keyring/ Edit: I'd like to add, I am loving Emacs and Clojure. I think it's worth the slog, but there is room for improvement for making a lot of these systems more approachable to the complete newcomers.
- photochemsyn 4y agoThe code examples shown here are highly confusing, and would benefit greatly from code comments. One of the most nonsensical trends I've seen in programming is the notion that 'code should explain itself' and if it's well-written, extensive comments are unnecessary. The best way to improve this post would be to append comments to each discrete code section, explaining clearly what other code sections it interacts with, what it's intended to do, and any other notes needed to clarify the functionality.
- StreamBright 4y agoUsing JS to try to prove or disprove anything is pointless. I think a much better comparison is C# / F# for the exact same problem. I think Scott Wlaschin's Railway oriented programming is a prime example of a great OOP vs functional programming content.
- jve 4y ago> I think a much better comparison is C# / F# for the exact same problem As a current reader of fsharpforfunandprofit.com, I'd like to see modern C# comparison with F#. C# has introduced decent pattern matching, records, nullables. LINQ was introduced long time ago - many things that make F# possible. Here is some comparison, but its 10 years old without the goodies C# offers today: https://fsharpforfunandprofit.com/posts/designing-for-correctness/ https://fsharpforfunandprofit.com/posts/designing-for-correc...
- superasn 4y agoJust watched a video(1) about functional programming and this is the gist of it (for those like me who don't know). Three main things of functional programming: 1. Keep your data and function independent 2. avoid changing state of variables, instead declare others 3. accept function/reference as a param (1) https://m.youtube.com/watch?v=dAPL7MQGjyM&t=3s https://m.youtube.com/watch?v=dAPL7MQGjyM&t=3s
- ergonaught 4y agoI have grown impatient with writing which purports to educate or inform people who do not understand a topic yet is completely incomprehensible unless one understands the topic. Practice some "Feynman technique" on your subject, or resign yourself to producing a suggested reading list of works that actually explain the topic, or please for the love of cognition stop masking signal with your noise.
- twawaaay 4y agoI 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.
- substation13 4y agoExcuse me sir, do you have a moment to talk about Functional Programming? I love FP and I think it makes writing robust software easier. However, I don't think the benefits can be explained well. The only way to see it is to give it an honest try - in a true functional language. This is too much of an upfront commitment for the unconvinced.
- rvalue 4y agoi 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?
- mrkeen 4y ago> 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? No. This is optimised away. It's yet another reason why it's frustrating to see FP-like things bolted onto mainstream imperative stuff. You can't optimise away 'mostly functional' code. Wrapping a Set with an UnmodifiableSet isn't the same thing as (f x) + (f x) == 2 * (f x)
- tome 4y agoThat’s interesting, because Haskell is the first language I have found in which I can write code, come back to it six months later, and still understand it. I never managed to do that in C, C++, Java, Perl or Python.
- 752963e64 4y ago
- Waterluvian 4y agoI’m a fan of pure programming because of its predictability and testability. And I’m a fan of chaining array functions to make a data processing pipeline obvious. I like how these can be opt-in and don’t require a totally different paradigm/language/architecture. I’m guessing this may be seen as a part of FP but not the core?
- BerislavLopac 4y agoWhen it comes to programming, pretty much everything boils down to two key elements: - 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.
- thaway34453 4y agoYou can marry FP with object oriented notation, see UFCS or Scala, or lenses.
- BerislavLopac 4y agoOf course you can, and that just strengthens my point. :)
- valenterry 4y agoThere really needs to be a more clear separation between functional programming (a very unclear and ambiguous term) and pure functional programming (formerly just functional programming, short and well defined but with huge implementations)
- mrkeen 4y agoYes, but pure means different things in different contexts. For language designers, purity is about the language itself, not what you're doing in it. E.g. Haskell is still a pure language even when you're reading and writing files. I don't think it's as useful a definition than the lay definition of purity.
- valenterry 4y agoI don't think that's really true. It's called "programming". Even Haskell is not a 100% pure-functional language since you have escape hatches. I think we should focus on what you do with the language, hence "functional programming" is pretty clear as a term no?
- substation13 4y agoAlice: I don't need functional programming, I am very productive in my imperative / OOP language. Bob: What about feature x? Alice: Oh yeah, well we can add that! It has proven useful. Bob: Agreed! But now do you see the need feature Y? Alice: Hmm good point. Feature X would be better with Y. Let's add that too. (Repeat n times) Alice: Isn't my language pretty nice now? Bob: I have to agree, it's very productive Alice: See I told you, we don't need an FP language after all! Bob: ...
- draw_down 4y ago
- FpUser 4y ago>"What’s so great about functional programming anyway" Well, nothing. It is one of many paradigms. It has its place just as the others.
- booleandilemma 4y agoThe 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.
- gspencley 4y ago> To hear some people talk about functional programming, you’d think they’d joined some kind of cult. I know that the chapter and book is coming at the topic pro-functional, and there's nothing wrong with that. But boy does that sentence ever ring true as a web application developer. Functional brings with it a set of core principles and values that provide a lot of benefit. So does OOP. So does procedural. I'm a fan of always picking the right tool for the job at hand. And JavaScript certainly brings with it a set of Functional-style features. Use them liberally, by all means. Let them solve problems for you. As a professional, learn as much as you can about Functional programming. Also learn as much as you can about OOP, imperative approaches, procedural and any topic that will be relevant to your field. Be the best professional that you can possibly be. But don't, for the love of God, try and write a modern frontend web application written in JavaScript (or TypeScript) from a "purely" Functional-first point of view. Not only will you fail and hate your life, but you will throw out lots of babies out with tons of bathwater. JavaScript is not even close to a Functional language. It doesn't matter if Brenden Eich wanted to bring Scheme to the browser, that's not what he ended up creating. Not only is it far from being a functional language, but I would argue that it is downright antithetical to FP. - Everything is mutable, even functions themselves. - Not only does JS have a mutable global namespace but modern frontend apps often have to deal with no fewer than FOUR shared global states (the global namespace, state management a la redux store, local storage and server-side persistence). If cookies still count then that might count as five. - Functional programming favours primitive types. Simplicity is the name of the game. Most client/server applications have to deal with rich domain models. Functional is great for "processes", while OOP is great for "things" (i.e: rich domain modelling and grouping data structures with the logic that mutates them). - The asynchronous event loop brings side effects as a core feature of the language. Yes we have strategies for putting our side effects in a corner, but the entire application is built from the ground up around the concept of side effects. Instead of taking simple input and producing simple outputs, we send things off to the server and/or update a global state store so that multiple things can update independently. Side effects are integral to a complex web application, no matter how many pure functions you write (and you should write pure functions whenever you can, they are simple, easy to test and debug). None of the above should matter except that I have come across many FP "purists" who come at the topic from a borderline religious angle. I think this has to do with how trendy our industry is. OOP was very hot in the 90s and 2000s. FP start to gain traction, at least in web development, with the advent of Scala and Douglas Crockford's JavaScript The Good Parts. There is a tendency in our industry to think in binary terms. That we saw lots of problems with OOP applications and FP is promising a solution therefore OOP = evil and FP = a gift sent down form the heavens to save our souls. Nothing could be further from the truth, and trendiness is the root of all evil IMO.
- petilon 4y agoWorth noting: the author of this articles does not believe React is functional: https://twitter.com/jrsinclair/status/1398780972506619907 https://twitter.com/jrsinclair/status/1398780972506619907
- horsawlarway 4y agoTo be fair - I mostly agree with that take. React with hooks is not functional. I think it's fair to say that React itself acknowledges this by making a distinction between a PureComponent and a Component. React itself certainly can be functional, but... (hot take) functional programming without the part where you actually make state changes is - drumroll - useless. If it ain't changing state and there are no side effects - no one gives a fuck. Because it literally isn't doing anything. Turns out computers are fundamentally state machines. Functional programming certainly has some nifty ideas, and it can be a helpful way to reason about code that will lead to state changes - but the part people want is the state change.
- lexx 4y agoBeautiful website. The transitions between the code blocks are a very nice touch
- larsonnn 4y agoJavaScript is a bad example. We rely on so many libraries which are not functional. React one of the biggest is not functional at all. Also JavaScript biggest advantage is that you can mix up. And it’s biggest disadvantage is that non experience developers will mix up too. Also you need to cloning multi level objects. To work 100% FP in JavaScript you need the libraries and you need to have a flat data structure every where. I don’t know how many JSON APIs you see who work like that. JavaScript has also a rich set of language features you can use to save your time and still have quality code.
- weatherlight 4y agoI'm a huge fan of writing code in an FP style in a language where that's the convention. Erlang, Elixir, OCaml, Clojure, (Hell, even Ruby.) The problem with the current state of JS and Its popular libraries, is that the convention is to write OOP and Imperative code. Unless your entire team is onboard, its causes a lot of issues. I feel like js-transpiled languages like Purescript, Rescript, ClojureScript, ReasonML, etc do a really good job of allowing Devs to write functional code on the frontend, while leveraging the JS-lib ecosystem. I personally have a hard time reasoning about while and for loops, etc, and mutable variables, my monkey brain can't keep track of that many spinning plates.
- sidlls 4y ago"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.
- dsnr 4y agoThe gazillion of lines of imperative C/C++ code out there that every OS runs on, are probably written by less than intelligent people.
- npc12345 4y ago
- bordercases 4y ago
- goatlover 4y agoLike Linus Torvalds. Lispers tend to make similar claims. So does Alan Kay about Smalltalk. Yet most of the world runs on top of C/C++, or COBOL (or Java) for financial transactions and Fortran for heavy duty numerical calculations. Not that FP, Lisp and ST don’t have their advantages. They clearly do. But their supremacy is overstated when it comes to code that runs the world.
- senand 4y agoThat doesn't mean the imperative languages are "better", though, just more popular. I recommend the following video titled "Why isn't Functional Programming the Norm?": https://www.youtube.com/watch?v=QyJZzq0v7Z4 https://www.youtube.com/watch?v=QyJZzq0v7Z4
- goatlover 4y agoSure, I'm skeptical that any paradigm or PL is superior in general, it probably all just depends on various factors.
- thaway34453 4y agoI do FP in JS, but I don't use Result or Option types or pipes because they are not part of JS's lingua franca. But I expect everyone in JS to be comfortable with `Array.prototype.map`, `Array.prototype.reduce`, and closures as these are core tenants of the language.
- mike31fr 4y agoAfter 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.
- runevault 4y agoLearn FP with a language designed to be FP instead of one that has the tools for it but isn't primarily meant to be used that way. See: Ocaml, f#, Haskell if you want to go all the way off the deep end, etc.
- vasergen 4y agoFor me, the second variant with map chaining const dataForTemplate = notificationData .map(addReadableDate) .map(sanitizeMessage) .map(buildLinkToSender) .map(buildLinkToSource) .map(addIcon); is the best one, it has way less mental overhead comparing with the end result. Also a catch with no error handling try { return Just(JSON.parse(data)); } catch () { return Nothing(); } in most cases is not the best idea, at least I'd put a log about it Nevertheless, waiting for the book from the author UPD: edited code formatting
- toastal 4y agoIt's not performant though generally speaking you keep boxing and unboxing the type (imagine having a list of 100,000 notifications and then mapping over it 5 times in a row). The composition law would give you a just-as-readable option const dataForTemplate = notificationData.map(pipe( addReadableDate, sanitizeMessage, buildLinkToSender, buildLinkToSource, addIcon )) > in most cases is not the best idea, at least I'd put a log about it Well, in FP you don't want to do side effects like write to console. Instead you want to hold onto the errors (with an `data Either e a = Left e | Right a` instead of `data Maybe a = Just a | Nothing`) til you get to the part of your application where you do do the side effects. try { return Right(JSON.parse(data)) } catch (err) { return Left(err) }
- EVa5I7bHFq9mnYK 4y agoI always thought the benefit of FP is thread safety, at the cost of a lot of data copying.
- blurbleblurble 4y agoWhat's great about it for me is helping me stay focused on one thing at a time. Composing and writing pure functions is easier for me to reason about as someone with an easily distracted mind.
- ouid 4y agofunctional programming has the same use to a programmer as category theory does to a mathematician. It is very good at describing the kind of objects we tend to care about, so it is sensible to consider the converse and ask what kinds of things is it good at describing. how naturally we can express our code is a very strong measure of how well we understand it. Both in terms of what it can and cant do. Imagine having blocks that stick together like legos, but you cant see the dot lattice because your vision is too poor. FP is about seeing the dots.
- teg4n_ 4y agoNever go full FP in JavaScript. I had a tech lead try to reinvent Haskell in JavaScript and everyone else in the team had such a difficult time dealing with their code it was ignored as often as possible. When you start seeing shit like a “blackbird” function to compose some other functions and you have absolutely no clue wtf the point of it even after reading the source and genuinely trying to understand you start to feel stupid and a bit resentful lmao.
- inawarminister 4y agoI'm having a good time doing Data-Oriented Programming (which is applying Clojure-style programming to other languages, in my case Python). IMO, chaining functions together rather than mutating objects and variables seem to be the most Pareto efficent takeaway from FP (at least in the Scheme/Clojure style, haven't tried F#/OcaML or Haskell). And HOP, though Python has native support for map and reduce and filter in the last few years, so great enough. And to be honest when I try to do something complicated in Clojure I end up blowing the stack anyway. Recursion is a bit too hard to grasp for non-programmers like me.
- kriro 4y agoI basically write code in any paradigm but (loosely defined) FP feels very natural to me. Immutable data and thinking about how functions get some input and provide some output is the most natural way of thinking about a domain for me. I have no good way of describing what I mean but I tend to think about functionality not things/items first I guess.
- commandlinefan 4y agoThe main problem with functional programming is that most programmers are too incompetent to use it. It's complicated, the way calculus and music are. While it's sort of a safe assumption that anybody outside of the actually learning disabled, with enough concentration, could buckle down and learn it, most people - so most programmers - won't. Most programmers won't advance past procedural code - that's why Java programmers love the singleton pattern and the Spring "framework" so much: it lets them write and think in simplistic procedural form but pretend they're using an object-oriented programming language. (And if you can't even comprehend OO, you definitely can't comprehend FP).
- 62951413 4y agoI'm still waiting for a FP equivalent of the original GoF book to learn it from. * https://leanpub.com/sofp https://leanpub.com/sofp is impressive but is in a different category * https://www.manning.com/books/functional-and-reactive-domain-modeling https://www.manning.com/books/functional-and-reactive-domain... is the only one I know which was trying to discuss building real life software
- adamwk 4y agoI wonder if the return of value semantics in languages lessens the appeal of FP. Localized mutation lets you manage side-effects but you don’t need to bring in an esoteric discipline of math to harness it.
- germandiago 4y agoI think functional programming is great for scaling systems but too restrictive since everything is immutable... So the model of the future, in my opinion, should look more like https://www.val-lang.dev/ https://www.val-lang.dev/ https://www.open-std.org/jtc1/sc22/wg21/docs/papers/2022/p2676r0.pdf https://www.open-std.org/jtc1/sc22/wg21/docs/papers/2022/p26... This is less restrictive and also very scalable IMHO. Value semantics, basically.
- mrkeen 4y ago> I think functional programming is great for scaling systems but too restrictive since everything is immutable... It's how things work at scale too. Source control? Git Money? Ledgers Distributed computing? Map-reduce, Raft
- germandiago 4y agoLol. True. Concurrency without stopping...
- AtNightWeCode 4y agoThe science says the math approach to programming is wrong. That is why the langs with very little need of understanding of math are the popular ones. It's the langs where people can be more productive and more easily be able to do things like code reviews. The topic is just silly.
- throwaway2037 4y agoOne 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.
- wtetzner 4y ago> If you are using containers, always, always, always use immutable containers from Google Guava unless you have an exceptionally good reason. I actually prefer pcollections: https://github.com/hrldcpr/pcollections https://github.com/hrldcpr/pcollections AtomicReference + immutable data types is a really nice way to program in Java, and is basically the way most Clojure programs are written.
- acchow 4y agoRead the example about “producers” - If I chain a whole bunch of producing together across many different Pcollections, I’m essentially forming a graph behind the scenes? Since no copying is happening Surely this would cause some strange performance outcomes with, say, a gradually built up immutable list.
- wtetzner 4y agoWhat do you mean by “strange performance outcomes”?
- valtism 4y agoWhen talking about writing lodash V5, jdalton (the creator) said "No FP wrappers. That fad is over. RIP your co-workers if you introduced that headache into your codebase. Definitely not team or human friendly." [1] To me, this sort of FP seems to have been tried and have failed. I don't know how much of this is due to the language and how much is due to the pattern not working well in the minds of developers. I wonder if JS had an implementation of something like C#'s LINQ if it would be easier to write code this way. [1] https://twitter.com/jdalton/status/1571863497969119238 https://twitter.com/jdalton/status/1571863497969119238
- neonate 4y agoWhat does FP wrappers mean in this context? Someone asked that in the Twitter thread and got a snarky response, but I have the same question.
- rahkiin 4y agoI think they mean what in lodash was _() and .values(): You could not execute map or filter on an array. Instead you needed to wrap it in a lodash object using _(arr), that you can call .filter() on. To get the filterd values out, you call .values() on its result. You could also do _.filter(arr, …). To me it became confusing when I needed to use .values, and when nesting it got worse. LINQ has instead methods on its types that partially returns builders. I find that easier to use, and using C# type system it calculates the result types for me.
- onetom 4y agoomg, so much negativity here... you should read the previous articles from the author, eg. https://jrsinclair.com/articles/2022/javascript-function-composition-whats-the-big-deal/ https://jrsinclair.com/articles/2022/javascript-function-com... then https://jrsinclair.com/articles/2022/what-if-the-team-hates-my-functional-code/ https://jrsinclair.com/articles/2022/what-if-the-team-hates-... it would address some of the concerns and critiques ppl had on this topic here.
- zactato 4y agoObviously the best part of Functional Programming is arguing about the pedantics of whether a language or construct is actually "functional"
- bob1029 4y agoFP 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 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.
- UK-Al05 4y agoNearly every system I worked on that had significant business logic in SQL turned out to be a maintenance nightmare. Used to be a lot of this in the 90s or early 2000s. Where dB venders encouraged it for obvious reasons. SQL isn't built with sensible decisions. Delete/update forget a where clause? Whoops. Lots of traps like that. Also it's not easily testable. Domain concepts don't always easily map.
- primeblue 4y ago
- alexvoda 4y agoPart of the reason is that SQL is simply a bad language (the JavaScript of databases). Part of the reason is also the thinking and philosophy behind DBMSs as interactive systems. Especially with regards to code. A function doesn't just exist. You create a function and it lives in the database until you alter it or drop it. This creates a different (temporal?) impedance mismatch with standard code management tools like version control. The result is most often a maintenance nightmare.
- dgunay 4y agoAn aside that I've been wondering about for a while with FP. I tend to use a lot of tools that do things like cyclomatic complexity analysis, test coverage metrics, etc. It seems like one goal of this style of FP is to abstract away control flow itself - why bother with if-statements when you can compose automatically short-circuiting monadic APIs like Option and Result? An admirable goal that I am 100% in favor of. However I feel like it might also obfuscate untested branches in source code and artificially minimize computed cyclomatic complexity if the tools are not aware of these control flow abstractions. I guess it's not super important in the grand scheme of things (I'm well aware of cyclomatic complexity's dubious usefulness as a metric).
- toolslive 4y agoIn the end, it boils down to the insight that functions compose better then classes, interfaces and objects. Also, OO and relational databases don't like each other. On the one hand you have trees as basic weapon for composition while on the other hand you have something where a tree is taboo.
- light24bulbs 4y agoHow are the types not totally screwed up in this kind of pattern? I get that this is JS, but since most of us at the level to be reading this post actually write TS, isn't it true that most of those transformations actually modify the type of the object, and therefor each would need to have a slightly different intermediary type? When I actually have this problem, I usually define the input as an interface and the output as another interface(maybe extending the input interface). Then I write a SINGLE function that calls those other functions, collects the data into variables, and then builds a new object of the new data type, and then returns that. Maybe I'm missing the point here.
- stevenalowe 4y agointeresting examples, but not compelling, i.e. procedural code to do the same thing would also work (and might be easier to understand for some). the thing i loved about FP was the elimination of exception handling the thing i disliked about FP was how complex classes were implemented as bizarre templates of structured list subtypes - too much focus on the data types and structures of the implementation, obscuring the domain-model (aka business) types and structures required for human comprehension. disclosure: scala, a few years ago there is a happy medium...theoretically
- sbf501 4y agoOne downside is that you now have a much higher bar for hiring talent to do trivial things. If you don't understand FP at a fundemental level, you will have a hard time finding people to work on your systems. Junior/Senior engineers are meant to be fungible to an extent. This ups the bar to a new language: this ain't JavaScript, it's an entire conceptual framework on top of JavaScript. EDIT: That being said, I really want to read this book!
- deleted 4y ago[deleted]
- sriram_malhar 4y agoWhy 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}` } });
- jongjong 4y agoMy view of FP is that it's not compatible with the concept of modularity or separation of concerns. If your priority is to ensure that similar concepts are grouped together inside flexible and composable modules, then co-locating related state and logic is necessary. Unless a module can fully encapsulate (have full ownership over) the state which it operates on, it cannot fully separate its concerns from that of other modules. If you have a global state store and any module can potentially read from and write to any part of that state, then you are bound to end up with modules which have overlapping responsibilities - These 'modules' won't be very modular or composable because, whenever multiple modules share the same state, they invariably end up having to have an awareness of each other's behaviors (to avoid writing conflicting state changes or to know when they should update themselves). Underlying FP philosophy is the notion that there is no value in encapsulation; that there is no value in assigning exclusive ownership over specific state to a specific module; that such ownership is dangerous because it makes the module unpredictable from outside. What FP proponents fail to realize is that once they've rejected the philosophy of state encapsulation, they've implicitly accepted the philosophy of state multi-ownership. Whenever you have shared ownership of state, it becomes unclear who is responsible for that state; this leads to potential conflicts. Avoiding conflicts forces modules to become aware of each other's existence and interactions and this reduces their modularity. The functional programmer's need for modules to be fully predictable with each interaction was born out of a need to micromanage them. On the other hand, OOP proponents understand the value of module autonomy and see them as black-boxes which need to be trusted to do their work. OOP proponents understand the value of simple interfaces when it comes to modularity and they understand that such simple interfaces are only possible if the module has sufficient autonomy and this requires it to have full control over its state. An analogy for FP in the real world would be like a computer manufacturer relying on chips from a chip manufacturer, but the computer manufacturer insists that the chip manufacturer must produce chips using only the materials provided by the computer manufacturer... Let's say that, eventually, a new superior semiconductor material is discovered; the chip manufacturer will not be able to use it to improve their chips. Although it has autonomy over its manufacturing processes, it is constrained to the materials provided to it by the manufacturing company; therefore it cannot take advantage of the innovation behind the scenes without the computer manufacturer also updating its processes and materials. The chip manufacturer is predictable but it is not modular; it cannot improve itself without involvement from the computer manufacturer.
- jrvarela56 4y agoThe 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
- uzbit 4y agoTo me it just seems like different syntax for different types of abstraction, not based on the OP, but from my own trials. Depending on how the calculation needs to be handled, one or the other may be more useful. As with all conceptual constructs, there's likely more than one conceptual projection in which it can be viewed with maximum clarity.
- pharmakom 4y agoWe don’t need functional programming! - OOP developers, as their languages gradually port all functional programming language features