I spent some more time looking into this since I couldn't wrap my head around it from just the talk. As far I as can understand at this point:
The fundamental logical unit of execution is called a reactor; reactors very precisely specify all inputs and outputs (called "ports") which can be hooked up to other reactors. Each reactor can contain a piece of logic which transforms its inputs into outputs.
There is a central coordinator service on the system which lets each reactor know whether it is safe to advance logical time
A reactor's computation (and global logical time) will not advance until all expected inputs at its ports have been received (I think?)
Due to the central coordinator aspect this paradigm isn't yet proven for distributed systems, although the talk speculates Google Spanner-type systems could be adapted to use it (with their associated extreme reliance on very precise synchronized hardware clocks)
This seems like a pretty cool choice for tiny embedded systems that do things like read sensors & output commands to motors. For example, the RP2040 is one of the premier supported platforms. If I were working on a fun robotic hobby project I would probably choose this.
What confused me quite a bit was the definition of determinism here. It is not determinism in the sense of like an Antithesis-style deterministic hypervisor where the same sequence of CPU instructions is executed across multiple executions. The measure of determinism is that particular outputs (for example, sending text signals to the "print to console" reactor) will be identical & seen at the exact same logical time (called a "tag") assuming all external inputs (disk read returns, sensor reads, random number generation) are injected with the exact same value and logical time. This is not true of regular thread-style concurrency, where the system (or runtime) thread scheduler can arbitrarily skew the output across otherwise identical executions. The primary author of this reactor-driven programming style wrote a paper called The Problem With Threads back in 2006 and has been banging this drum ever since.
I watched the ICFP talk too and while the research is interesting, I'm not really convinced by the practical benefits. Defining all external events and their timestamps as inputs makes the model deterministic, sure, but it doesn't make network failures, delays, or recovery go away. The answer to the fault tolerance question was basically "we can detect timeouts", which isn't quite the same thing. Seems like a lot of complexity for a fairly narrow benefit, at least outside embedded and real-time systems. But definitely intriguing.
What's the motivation for being polyglot? Is it along the lines of "whatever language we use we have a solution for you" or is it intended to be the central programming paradigm across all devices: servers, clients, etc?
seamless transition between single- and multi-threaded = the job of the compiler/runtime (several datalog engines can run using any number of threads, and you don't really need to think too hard about it)
timing ~= stratification + a parallelization strategy using clocks, e.g. differential datalog which implements on top of differential dataflow, which benefits from its clocks. There are also datalog variants with explicit notions of time and state update, though their ability to be parallelized is less clear to me.
fully specified inputs=the clause body
fully specific outputs=clause head variables
connection between inputs and outputs as range restriction
logic per reactor = extralogical functors execution in clause bodies
I think it kind of boils down to thinking about the (intermediate) relations as being potenitally ephemeral, rather than fully reified and persistent for the rest of the execution as they often are in in Datalog.
jtm | 9 hours ago
There was a talk at ICFP (posted on Lobsters a couple weeks ago) that gives a really nice overview of the design and research behind the language.
ahelwer | 5 hours ago
I spent some more time looking into this since I couldn't wrap my head around it from just the talk. As far I as can understand at this point:
What confused me quite a bit was the definition of determinism here. It is not determinism in the sense of like an Antithesis-style deterministic hypervisor where the same sequence of CPU instructions is executed across multiple executions. The measure of determinism is that particular outputs (for example, sending text signals to the "print to console" reactor) will be identical & seen at the exact same logical time (called a "tag") assuming all external inputs (disk read returns, sensor reads, random number generation) are injected with the exact same value and logical time. This is not true of regular thread-style concurrency, where the system (or runtime) thread scheduler can arbitrarily skew the output across otherwise identical executions. The primary author of this reactor-driven programming style wrote a paper called The Problem With Threads back in 2006 and has been banging this drum ever since.
kaycebasques | 5 hours ago
You know it truly comes from academia when the homepage does not label the docs as "docs" but rather "handbook" ;P
But also I mention this to direct people to the docs that seem to provide much more info than the landing page: https://www.lf-lang.org/docs/
edit: to be fair the landing page has a clear "read the docs" CTA. it's only the mobile menu that says "handbook"
gkoos | 5 hours ago
I watched the ICFP talk too and while the research is interesting, I'm not really convinced by the practical benefits. Defining all external events and their timestamps as inputs makes the model deterministic, sure, but it doesn't make network failures, delays, or recovery go away. The answer to the fault tolerance question was basically "we can detect timeouts", which isn't quite the same thing. Seems like a lot of complexity for a fairly narrow benefit, at least outside embedded and real-time systems. But definitely intriguing.
kaycebasques | 5 hours ago
How is the code size when compiled for embedded?
What's the motivation for being polyglot? Is it along the lines of "whatever language we use we have a solution for you" or is it intended to be the central programming paradigm across all devices: servers, clients, etc?
pag | 4 hours ago
This sounds like Datalog.
jtm | 3 hours ago
How so? I’m not sure I see the connection.
pag | 3 hours ago
It's a simplistic take! But how I look at it:
seamless transition between single- and multi-threaded = the job of the compiler/runtime (several datalog engines can run using any number of threads, and you don't really need to think too hard about it)
timing ~= stratification + a parallelization strategy using clocks, e.g. differential datalog which implements on top of differential dataflow, which benefits from its clocks. There are also datalog variants with explicit notions of time and state update, though their ability to be parallelized is less clear to me.
fully specified inputs=the clause body fully specific outputs=clause head variables connection between inputs and outputs as range restriction logic per reactor = extralogical functors execution in clause bodies
I think it kind of boils down to thinking about the (intermediate) relations as being potenitally ephemeral, rather than fully reified and persistent for the rest of the execution as they often are in in Datalog.