11 ms·
A fun essay that really tries to nail down the "Why" in a real-world way. It mentions that functional programming removes the tripwire of state mutation as one
by clusterhacks 4y ago
A fun essay that really tries to nail down the "Why" in a real-world way.
It mentions that functional programming removes the tripwire of state mutation as one of the "whys", but my experience slightly differs here.
I found, after years of struggling with the "why" of object-oriented programming and its early obsessions with design patterns, that functional programming simply resonated with me personally. To this day, I have a bit of inner cringe when reading (for example) Java code.
Early in my career, I thought my lack of "getting OOP" was due to some profound missing piece of understanding. But then Lisp (and Clojure) just made sense. Thinking functionally just works for me. It's not so much that I couldn't use OOP but just that each time I worked in deeper OOP projects, I felt some internal friction or vague uneasiness with the code.
I did find that functional programming made me significantly more comfortable with OOP languages. YMMV.
- drnewman 4y agoMy experience has been exactly the same.
- orangepurple 4y agoThat friction and vague uneasiness for me is as the nagging thought that it's simply not correct code. In my case I prefer to write as much SQL as reasonably possible to prevent having to write any code in an imperative language.
- klysm 4y agoI’m very much in this camp as well. A significant number of applications can be expressed with sql and a thin layer around it
- adamddev1 4y agoInteresting. You mean make all the queries as detailed and specific as possible, processing things as much as possible in SQL so you don't have to mess around with the data you get from/put in the DB in an imperative langauge? Do you have any good examples of this? Code bases that can be read?
- orangepurple 4y agoMessing with data significantly outside of SQL is often asking for trouble. SQL queries are compiled into very efficient operations which would take a lot longer to get right imperatively. Not only that, but database engines are improving all the time, so the same code you wrote which declares your desired transformations tends to get faster over time and there is nothing to update or refactor. The transformations you write are sort of timeless because they are strongly decoupled from the implementation and hardware. Lots of data transformation steps in imperative languages require the persistence of an intermediate calculation (e.g., np.ndarray). SQL database only do this when the query planner deems it absolutely necessary. It will show up in your query plan as a "materialize" step. The EXPLAIN feature of SQL is the most useful performance debugging tool. It also alerts me to a potential logic flaw quickly when the proposed plan looks insane. I have personally replaced several analytical programs a very large bank used to monitor loan originations and performance. I don't use any special SQL language features to this day. The most sophisticated it typically gets is involving lots of subqueries, joins, and window functions. The real skill is distilling the convoluted imperative mess into its essence. I got really good at this. Half the work effort is usually spent on socializing the changes I have to make to their logic to get it working right in SQL when it changes the behavior of their existing application's logic. Often times I find the client's imperative code attempting to perform a logical operation such as a join but it is implemented incorrectly. Their existing imperative code operations actually produced the wrong results (subtly) frequently or their imperative code depended on the order of the data returned from the database (undefined behavior). Yikes. What they actually wanted was provably implemented incorrectly or relied on undefined behavior and their mistakes and the proper resolution in SQL could be easily verified with paper and pen on a sample set of loans if necessary to drive the point home.
- adamddev1 4y agoVery cool. So you write it with solid, declaritive SQL and you can trust that it will be rock solid and optimizied. Need to learn SQL instead of just doing NoSQL all the time. Thanks for the explanations.
- 4y ago
- oedo 4y ago+1. And the subset of those applications concerned with simply converting result sets <-> JSON over HTTP may well even tolerate use of an API generator (eg PostgREST, PostGraphile, Hasura), reducing that thin layer to merely a membrane.
- FpUser 4y agoI am not against / for any reasonable paradigm. I use multiple however I see fit depending on particular situation. Never wanted to be a "purist".
- Tao3300 4y agoIndeed. Sometimes it's more obvious to say "here are the steps to make this thing, now go" and sometimes it's more obvious to say "here's a description of the things I want."
- adamddev1 4y agoMe too. I've also been trying to learn more about OOP and reading "Smalltalk, Objects and Design" bc I heard a lot about how Smalltalk is the real, good OOP. But there were points I just felt squeamish, like when they were talking about the danger of the difference of effect vs. output on methods where I felt anxiety and thinking "ooo, why would I wanna do that??" I can just feel my code getting messier... Some ideas like using polymorhism to avoid branching conditionals was interesting though and I'm sure there's times it can be helpful.
- bcrosby95 4y agoI'm pretty similar. People like to ask "why should I use <insert language>?" I never really think about it too much - I don't pull out my weights and measures, and say "well, language X is 83.72% optimal for the problem, but language Y is 91.22% optimal, obviously using language X is a huge mistake!" If something is obviously better for a problem, I'll pick that language. But if you have to dig too deeply into what language to use, the language probably doesn't actually matter that much. I was "raised" on OOP, and I "got" it, but I've always preferred more standard procedural programming. I prefer Go over Java, and C over C++. I like FP more than procedural programming. I prefer Elixir and Haskell over Go. I like Lispy languages more than other languages. I prefer Clojure over Elixir and Haskell.
- agumonkey 4y agosyntax, imperative statements and classical object verbosity and inappropriate structure always hurt me whenever I read a lisp / ml book, I sweat a bit and then I gain superpowers and insights, whenever I read mainstream OO books I just get a neverending stream of "please stop.. why ??" and it's not only lisp to be frank but a mindset that lisp embodies a lot.. even using an hp48 felt better than basic+algebraic programming calcs .. (at the time I had no idea what was RPL)
- 13415 4y agoFor me, it's the opposite, I like Lisp and Scheme because they don't force me into one programming paradigm. I'm not very fond of FP but used OOP almost in every project when I was programming in Racket (for a decade or so). I often wrote more functional code first and then wrapped it into classes to "assemble" it under one roof. Lisp and Scheme are great languages for object-oriented programming.
- drnewman 4y agoMy comments where not at all to make a statement about FP vs OOP, for me they both have their place, and I agree that Lisps are great OOP languages. It just turned out for me that FP came more naturally as a new programmer, and learning about the subtleties of lambda the ultimate, lexical scope and state from an FP perspective helped me to finally feel like I grok OOP. I was pleasantly surprised to see someone else express a similar sentiment.
- ducktective 4y agoShow me a GUI framework that follows FP patterns not OOP.
- skruger 4y agohttps://phoenixframework.org/ https://phoenixframework.org/
- fredrikholm 4y agoOff the top of my head: * React * Elm * Halogen * Phoenix * Phoenix LiveView * Re-frame * Reagent
- fny 4y agoSwiftui
- pjmlp 4y agoReact is using JavaScript OOP, with the instances of JavaScript objects for data types and DOM manipulation, it doesn't exist.
- hajile 4y agoReact moved away from OOP quite a while ago. It's mostly pure functions and closures that return what are functionally records. When the JS tuple/record proposal is finally implemented, I suspect they go even farther in that direction. Of course, you could argue that closures are simply objects with one method (or that objects are a poor man's closures), but that's a rather pedantic line of discussion.
- felideon 4y agoWhich is funny, because OOP should be[1] about the in-between of the objects: the messages[2]. Not about the objects themselves or the classes and GOF design patterns. With Common Lisp you get generic functions and design your classes around those. [1] “OOP to me means only messaging, local retention and protection and hiding of state-process, and extreme late-binding of all things. It can be done in Smalltalk and in LISP. There are possibly other systems in which this is possible, but I'm not aware of them.” - Alan Kay (http://userpage.fu-berlin.de/~ram/pub/pub_jf47ht81Ht/doc_kay_oop_en http://userpage.fu-berlin.de/~ram/pub/pub_jf47ht81Ht/doc_kay...) [2] “The key in making great and growable systems is much more to design how its modules communicate rather than what their internal properties and behaviors should be.” - Alan Kay (https://wiki.c2.com/?AlanKayOnMessaging https://wiki.c2.com/?AlanKayOnMessaging)
- gmfawcett 4y agoWe should stop invoking Alan Kay's ancient opinion in OOP discussions. I suggest we rebrand his flavour of programming as "message oriented programming" (MOP), thank it for its continuing contributions to the field, and recognize that contemporary OOP is a valid but different solution space.
- felideon 4y agoClarity is certainly important, in which case I could have said “OOP should have been...” Except: Smalltalk still lives (Squeak) and Erlang takes messaging to the extreme.
- Twisol 4y agoI've not used Erlang much, really, but it seems like a really nice fusion of messaging across agents and immutable state within agents. Elixir has long been on my list of languages to properly pick up...
- deleted 4y ago[deleted]
- 4y ago
- invisiblerobot 4y agoDon't stop there. I thought racket was the holy grail due to the macro system but my real metamorphosis came after learning Haskell. I realize now that my previous preference for Clojure was because I was stuck in prototyping mode. Once you truly understand your problem domain then types trump macros. So while I owe a huge debt to Clojure/Racket for rescuing me from my java nightmare, and introducing me to other approaches like Erlang, it was Haskell/Purescript that matured me the most as a programmer. It was so worth the (considerable) effort, because it has generalized the very nature of computation in a way that just never happened for me in all my years with lisp.
- AgentOrange1234 4y ago“Types trump macros” is a nice way to put it. Macros are amazing for creating new languages, but a good type system with strong case matching and sum types is just incredible to work with.
- invisiblerobot 4y agoI was in the process of creating my own language in racket. It was going to codify everything I had learned over the years into powerful abstractions and target JavaScript. Halfway though I realized I was inventing a shittier Purescript. Dsls are mostly masturbation. Custom syntax? Custom evaluation semantics? I always regret it after like cocaine. The only thing macros are reasonable for is custom bindings. Most people are not qualified to invent dsls. Myself included. And the people who are qualified don't need "language oriented programming" ala racket. They can spin up a lexer which is the least complicated part of the task anyway. As for types, they have a HUGE power to weight ratio. All of my efficiency gains in Clojure due to macros were forfeited 10x over hunting down null pointer exceptions at runtime. I still love Racket. And I still prototype in Clojure. But Haskell brings you closer to math. Closer to category theory. Most programmers don't need new symbols and semantics. They need a deeper understanding of combinatorial logic.
- rscho 4y agoRacket DSLs aren't the same as 'spinning up a new lexer' at all. Making DSLs is hard, and being a PLT expert does not make one an expert at language implementation. Those are completely different skills (see Brady's reimplementation of Idris on Chez Scheme and the reason for it). Racket allows people with new ideas to prototype them efficiently by easily implementing a compiler that would've been an interpreter otherwise.
- epolanski 4y ago> Early in my career, I thought my lack of "getting OOP" was due to some profound missing piece of understanding It simply does not have formal definitions and examples. Almost everything in OOP books and content is defined like "imagine you have this situation and you want to do this thing..." and then it starts with ships, containers, ports, cranes or animals and lions. The thing I like about fp is that there's surprisingly little things to know, and they all have formal definitions. The definitions are also quite simple and build on previous definitions. If you know what a data type and a `map` operation is, you can easily understand a functor. You add to it another ingredient and you have an applicative functor. Another one, and you get a monad. You make small steps towards knowledge that are solid.