5 ms·
What Steve calls "Denotative Continuous-Time Programming" – I think Clojurists call this declarative data programming – that is, you figure out a way to model t
by dustingetz 7y ago
What Steve calls "Denotative Continuous-Time Programming" – I think Clojurists call this declarative data programming – that is, you figure out a way to model the problem domain in data, and then write pure functions on that data. For example, React.js models the dom as data. Clojure gives you the toolkit of programming language primitives you need to do this easily, ergonomically and often, for all of your problem domains, not just virtual dom.
I think an example of database programming in "Continuous Time" would be
(datomic.api/q '[:in $ :find ?e :where [?e :post/title]] db)
where `db` is a time-pinned and consistent value of the database graph – in other words datomic.api/q is a conceptually pure function of time, time is a parameter, which implies you can rewind it or speculate into the future (both of which are supported by this interface)
As for abstracting HTTP – what if you considered network io as just a way to lazy load a cache of immutable database values? So for example, this would work a bit like Git – we don't care how the clone protocol works, just load me the file values I identified. Maybe it uses HTTP, maybe it uses something different, who cares? Get me the value I asked for in the fastest way possible given available infrastructure, distributed caches, etc.
Then, the question of IO resolves to: what categories of effects can be modeled as values and functions on values? Given declarative data programming in Clojure – basically anything!
- skybrian 7y agoYou can think of a timeline as immutable, but you don't know values from the past unless you arranged for them to be recorded, you don't know values from the future until they happen, and you don't know what's going on at any other node unless they send you a message about it and it eventually makes it across an unreliable network. (So, sometime after it actually happened.) If you model this in a declarative way then you have to be careful to avoid implying that all events should be remembered, and also avoid depending on anything in the future unless you want to wait for it. This makes designing an intuitive FRP-based language pretty hard.
- dustingetz 7y ago> be careful to avoid implying that all events should be remembered Is that true in a post-AWS world with storage getting cheaper faster than you can consume it? Maybe don't put 4k video in the log. But, you're right, we can stream, shard and forget as necessary. > also avoid depending on anything in the future unless you want to wait for it Can you elaborate on this, my gut reaction is to ask why I need to avoid depending on git commits that haven't been written yet – it's kind of a weird question right? Time is explicit now, which means you have the right knobs you need to coordinate it, even across distributed nodes.
- csande17 7y ago> Is that true in a post-AWS world with storage getting cheaper faster than you can consume it? This might be true of "storage" as in disk space, but it definitely isn't true of "storage" as in RAM. If your phone kept an in-memory log of every single click event, you'd run out of RAM pretty fast.
- skybrian 7y agoIf you use a value to do a calculation and it's from the future then often you end up blocking until it's available. This is how a Future works and is similar to what happens when you read from a TCP connection and the data has to be retransmitted because the network dropped the packet, so you block. If you want responsive output then you should avoid blocking or at least have a timeout and/or cancel button. The conceptual idea of a value that continuously changes is nice for animation or maybe video (though that's both discrete and lossy), but seems messier when your knowledge is limited to an unknown selection of discrete data points from that timeline, arriving with an unknown amount of lag? Maybe you could talk about that mathematically, but it seems like it's going to be rather abstract and messy.
- convolvatron 7y agoi think it falls into the slightly-too-clever category, but http://www.neilconway.org/docs/vldb2014_edelweiss.pdf http://www.neilconway.org/docs/vldb2014_edelweiss.pdf treats safe log truncation as a conservative optimization. its similar to tail-call in that the efficacy of your program depends on the compiler figuring out what you're trying to do - which is unsatisfying but its a great idea and a ray of hope here edit: this also implies that the set of reads against the history is fully known at compile time - which may make it irrelevant depending on the usage
- marcosdumay 7y ago> This makes designing an intuitive FRP-based language pretty hard. Yet, I fail to see any other representation where it is viable to solve those problems in a generic way. If we want to get something better than our current "it's impossible, better not even try" posture, we better look for it somewhere where it is possible.