3 ms·
I am sorry, but you sound like you know for a fact that functional programming is better, but you have trouble making others recognize that fact. Imho, FP has
by torginus 4y ago
I am sorry, but you sound like you know for a fact that functional programming is better, but you have trouble making others recognize that fact.
Imho, FP has many tangible weaknesses, just a few off the top of my head:
- Immutability is non-intuitive: If I were to ask someone to make an algorithm that lists all the occurrences of a word on a page, they wouldn't intuitively come up with an algorithm that takes a slice of text and a list of occurrences, then returns an extended list, and an linked list with one more occurrence.
- Immutability can cause more problems than solve: If I were to create a graph of friendships between people, chances are that if I were to add a link between A and B, then not only A and B would need to be updated, but everyone who transitively knows A and B (which, since no man is an island would probably mean, everyone). This is highly complex, and probably just as bad as living with mutability.
- FP is not performant: FP code tends to be full of pointers and non-performant data structures like linked lists that have very little memory locality. It also makes optimizations such as updating things in a certain order to avoid recalculation impossible.
- FP has to deal with side effects: The real world has side effects, and your FP code is probably a bit of business logic that responds to a HTTP request, and fires of some other request in turn. These things have unavoidable side effects.
- initplus 4y agoOn this friendship example, I think already FP is showing you something useful about the way you are designing your model. A friendship is really an edge in a graph. if you manage friendships by recording a collection of friend PersonId's on each person, you are modelling a graph by recording the same edge in two different places, and then hoping the programmer is diligent enough to never make a mistake and update the edge in one place but not the other. If you model the friendship graph as a collection of id pairs, not encapsulated inside a specific person structure, this invalid state is no longer possible. I'm not sure what you are on about regarding making transitive updates - that idea is obviously not going to work on any moderately sized network. Imagine if Facebook tried to record all your transitive friendships on your account! Sure immutability is non-intuitive, but it's really helpful! Like borrow checking in Rust, immutability helps eliminate an entire class of bugs. And immutable code is often much easier to reason about, you need to keep significantly less of the context in your head.
- hajile 4y agoFP isn’t just limited to Haskell while your criticisms seem aimed only at that one language. Immutability may not be intuitive, but neither are pointers, hash tables, structured loops, OOP, etc. In any case, maintaining immutable code is certainly more humane than trying to reason about 10th order side effects. Finally, the majority of functional languages are immutable by default with optional mutation when needed. Your immutable argument is a red herring. It’s the wrong algorithm. Bubble sort is much more intuitive than heap or quick sort, but you certainly wouldn’t recommend it. You are flatly wrong about performance. Ocaml and StandardML are just as fast as languages like Go or Java. This is incredible when you realize These FP languages are maintained by a handful of people with basically no budget and are keeping pace with languages that have tens out hundreds of millions of dollars pushed into them. FP doesn’t mean no side effects (though it does tend to encourage limiting and separating them). Outside of Haskell and Miranda, basically all the other FP languages have side effects and even Haskell has an escape hatch available.
- theCodeStig 4y agoHaskell has to have an escape hatch in order to work, though fortunately it is hidden away. Every program has effects. A program that does not have any effects (IO) would not be useful, as you can't get anything into or out of it. In FP we manage those effects, in order to help ensure correctness, with the additional benefit that good effect management makes the program easier to comprehend (nee reason about). Contrast a procedural program with effects littered throughout the codebase, with a program wherein effects are pushed to the edges. In the latter, you and your team know exactly where all of the effects occur. Everything else is pure code: easier to test, easier to comprehend, easier to compose. Category theory is not required for good effect management. It just so happens that monads like IO fit the problem space nicely; although the same could be achieved with a lazily evaluated definition of computation (i.e. a function).
- throwawaymaths 4y agoI think you're completely missing an entire world of FP languages which are not pure like Haskell, ocaml, elm, etc... There are languages with side effects as an easily accessible escape hatch but don't do things which make debugging a pain like data encapsulation and inheritance. Also, there are FP langs out there that have better data/heap locality with indirected pointer data structures, because they don't share memory and so the pointers aren't tied to anywhere except where they are directly running. I completely disagree with immutability being non-intuitive. Try explaining to a junior/bootcamp JavaScript or python developer why when you pass an integer into a function it doesn't reflect changes you made in the called function when you jump back into your calling frame... But if you do the same with a object/dictionary... For junior programmers immutable passing is absolutely the default assumption and so I think it's reasonable to claim it's the intuitive choice. There's even crazymaking shit where in python if you have a default array parameter you can seriously fuck up your model of what's going on if you mutate that array anywhere.
- agentultra 4y agoI think you haven’t read much of the literature and don’t have any real experience with it on a real project. There is no intuition when it comes to programming. Everyone has to learn it. You’re appealing to familiarity of concepts you’ve already learned and assume everyone else thinks the same way. There are highly efficient graph algorithms using pure immutable data structures. You don’t seem to be aware of how much sharing is enabled by immutability nor the algorithms for efficiently updating graphs in a pure functional way. Try reading this book [0]. Again there is a whole zoo of optimizations available exclusively to pure functional languages that you don’t seem to be aware of. Try reading Counting Immutable Beans. Some of the optimizations GHC can do are impressive. It’s not all bad performance. Want to talk about cache misses? Check out an average C++ code base. It has a dedicated cache-miss operator. Side effects are everywhere. And yes, in a purely reverentially transparent language, it becomes a pain being forced to be explicit about every mutation, network call, and file handle operation when you’re used to throwing caution to the wind and flying free with them. Improper handling of side effects include common use-after-free errors, etc. After years of dealing with this mud all of software, at least for me, explicit handling of effects becomes exactly what you want in order to keep your sanity intact. [0] https://books.google.ca/books/about/Purely_Functional_Data_Structures.html https://books.google.ca/books/about/Purely_Functional_Data_S...
- badsectoracula 4y ago> There is no intuition when it comes to programming. Everyone has to learn it. There is no intuition in anything aside from the very few things we are born with. Everything else is learned from experiences. And to that end, chances are someone has learned to follow procedure-like steps like a recipe at a very early age - indeed, in some schoolbooks recipes and other "procedural" works are among the first things someone does. Children learn things like "to do X, first do Y and then Z" from a much earlier age, often before even learning how to read and write (e.g. via simple papercrafting in kindergarden) than something like "X = Y*Z". Giving and taking commands (i.e. "imperative" programming) as a concept is something people meet in their lives much sooner and are more exposed to than abstract problems.
- 4y ago
- naasking 4y ago> - Immutability is non-intuitive: If I were to ask someone to make an algorithm that lists all the occurrences of a word on a page, they wouldn't intuitively come up with an algorithm that takes a slice of text and a list of occurrences, then returns an extended list, and an linked list with one more occurrence. What do you base this on? Did you run a study of people who had never programmed before and then asked them to invent a pseudo-programming language to solve this problem? Or are you talking about the "intuition" of people that have already learned to program, mostly likely in an imperative programming language, in which case your claims to "intuition" don't mean anything. > - Immutability can cause more problems than solve: If I were to create a graph of friendships between people, chances are that if I were to add a link between A and B, then not only A and B would need to be updated, but everyone who transitively knows A and B (which, since no man is an island would probably mean, everyone). This is highly complex, and probably just as bad as living with mutability. Firstly, that's not true, it depends entirely on what sort of data structure is used. For instance, a trivial model is a simple list of graph modifications, ie. type Action = AddFriend(a,b) | RemoveFriend(a,b), type FriendGraph = List(Action). Any change to the graph thus requires allocating only a single node. Secondly, if you were to model this mutably, a node removal means you would lose information about the fact that two people were friends at one time. > - FP is not performant: FP code tends to be full of pointers and non-performant data structures like linked lists that have very little memory locality. It also makes optimizations such as updating things in a certain order to avoid recalculation impossible. This argument is based on assumptions about the functional programming idioms, the compiler, the machine it's running on and more. I could just as easily say that imperative programming doesn't scale because you can't easily parallelize it across cores, and since single-core performance is now a dead end, even if everything you just said were true it's basically irrelevant for the question of performance. > - FP has to deal with side effects: The real world has side effects, and your FP code is probably a bit of business logic that responds to a HTTP request, and fires of some other request in turn. These things have unavoidable side effects. I'm not sure who denies this. The question is not whether useful software has side-effects, it's what sort of side-effects you actually need for any given program and how those side-effects should be modeled so you can properly reason about them and achieve the program properties you need. If your programming language has pervasive side-effects then you have to deal with them everywhere, and the failure modes multiply. If your programming language does not support pervasive side-effects, then the side-effects are pushed to the edges of your program where they are more amenable to reasoning. Questions like "how did we get into this state?" are considerably simpler to backtrace as a result.
- alanwreath 4y ago>> I am sorry, but you sound like you know for a fact that functional programming is better I can see the room for misunderstanding. My only argument is that FP is worthy of more playtime than it currently enjoys in undergraduate academia. I'd wager that the current percentage of FP/Imperative playtime is 95/5.
- torginus 4y agoAh I see. I've been out of school for a while so I don't know how students are taught - but if you take a modern language such as Kotlin, you'll see it's a mishmash of concepts from various paradigms, including FP.