6 ms·
Understanding and modelling IO is a big part of why Clojure took of like it did. Its functional, its pure-ish but it has an understanding of time, concurrency a
by lbj 8y ago
Understanding and modelling IO is a big part of why Clojure took of like it did. Its functional, its pure-ish but it has an understanding of time, concurrency and IO baked in. When you do IO time matters, take a look at how Datomic models this (incrementally).
But even from the early days, Rich Hickey said that no pure functional system exists as even an empty HD emits heat, which is a form of IO and I think we should listen to Hitchens and abandon our "fantasy of purity" when it comes to writing real software.
- mbrock 8y agoI don't think that's what functional purity means. Actually I think there are a lot of huge misunderstandings about this. It's kind of like, think about grammars of human languages. Obviously human communication involves commands. But you might still have a good reason to desire a grammar that is "purely functional" in its mathematical formulation. Pure functional programming is about establishing a certain level of formal discourse where expressions involving applications of functions reduce to values. It's not a fantasy where effects don't exist—it's a way of being precise about effects in a particular style of formalism. These expressions should be able to describe all kinds of systems, as indeed Haskell's IO type is extremely capable when it comes to describing multithreaded sequential computations involving mutable state and external effects. Conal is suggesting that the IO type is a bit crude compared to the full potential of "functional reactive programming" which is for sure a powerful paradigm.
- lbj 8y agoIm just going by the formal definition of purity 1. Its return value is the same for the same arguments (no variation with local static variables, non-local variables, mutable reference arguments or input streams from I/O devices). 2. Its evaluation has no side effects (no mutation of local static variables, non-local variables, mutable reference arguments or I/O streams). As soon as I/O is involved, functional purity is technically broken and since any real-world system will have I/O I consider the quest for purity to be a fantasy in the same vein as developers who invest a lot of resources in "proving" their functions.
- mbrock 8y agoFunctional purity isn't broken by Haskell-style I/O. In Haskell, I/O is not done through side effects, and I/O effects are not functions, so your points 1 and 2 are not violated. It's not a "fantasy." You just don't understand it.
- platz 8y agoThe post is really talking about choosing the best kind of composition to solve problems in (purity was a by-product of being mathmatical). You guys are arguing over the monadic io that he dismisses in the first couple couple paragraphs. All he really cares about is achieving program composition.
- atombender 8y agoAs someone who knows next to nothing about Clojure, what does an "understanding of time, concurrency and IO baked in" actually involve, compared to something like Haskell or OCaml?
- lbj 8y agoClojure has more than a handful of data-types which allow you to mutate/change values. You have 'ref' which allows for multiple observers and manipulators that all see a discrete timeline. Think of a bank-transaction where two withdrawals run in parallel would yield a negative balance. Refs prevents that. Refs are mostly for synchronicity. There's also atoms and agents to look at, but the overall perspective is that the world is as the world is and those who observe it always do so with some delay. The discrete timemodels allow you to have consistent views of the world from multiple observers. This is a the heart of Datomics data-model. Nothing ever changes. If you commit a fact like "fred likes pizza" at 2pm. Fred will always be known to have liked pizza at 2pm. If you later commit that Fred likes apples. That will only be true from the point in time in which you commit, but you'll still be able to see that fred used to like pizza. The IO is a side-note, but living on the JVM Clojure has native access to everything from files to streams and you can interact with them just like Java people do. There's a few helpers like with-io to manage multiple simultaneous writes, but they're rarely used. Haskell in this regard, has the IO Monad which is briefly commented on the article. Its sort of a trick and as I understand it Haskell has no ambition of being the go-to concurrency language. It has recently had something like Refs/STM added though, haven't looked into it much.
- atombender 8y agoThanks for the explanation. Sounds like Clojure allows mutation and side effects all over the place, but that it has some nice libraries for handling immutability and sequencing in various ways so that you can write consistent programs. That sounds nice, but also not particularly unique or interesting. The IO monad in Haskell is no trick, but I can understand why you would think that.
- 8y ago