Anti Assimilation

14 views
Skip to first unread message

Paul Tarvydas

unread,
Jun 19, 2026, 9:00:36 AMJun 19
to pi...@googlegroups.com

Raoul Duke

unread,
Jun 19, 2026, 7:53:09 PMJun 19
to pi...@googlegroups.com
i don't get it. "eliminating thread safety" problems is just playing whackamole: the same problems will surface elsewhere, the fundamental issue of state consistency will not magically go away??

Paul Tarvydas

unread,
Jun 19, 2026, 9:14:45 PMJun 19
to pi...@googlegroups.com

"Thread safety" is but a piece of accidental complexity caused by mapping the theoretical concept of synchronous "concurrency" (which is not the same as asynchronous "parallelism") onto synchronous, sequential hardware, such as a single CPU, using shared memory between processes. 

The thread safety issue can be wiped out by using processes that don't share memory. For example, nodes on an internet do not share memory and don't cause thread safety issues between one another. Software implementing a node can choose to continue to use a shared memory model internally, and, hence, will not fully benefit from the simplicity of eradicating thread safety. Internet nodes are asynchronously parallel, but software inside nodes that use memory-sharing concurrency based on the synchronous, sequential paradigm cannot be parallel and are only synchronously concurrent.

Multi-core, as I understand it, doesn't give full relief from thread safety issues.

Switching to a pure message-passing paradigm internally will cause evaporation of thread safety concerns. Using function calls only looks like message-passing, but is actually an impure form of message passing (I don't know of a name for this impure form ; functions block when calling other functions, hence, also pass control flow along with message data). Just about any modern programming language, especially those that conform to "calling conventions" fall into the category of being accidentally complexified.

I'll see if I can come up with a better explanation that de-conflates these issues. This will require some more thought and time...

Raoul Duke

unread,
Jun 19, 2026, 9:49:03 PMJun 19
to pi...@googlegroups.com
still doesn't fix the core issue of state coherence / consistency 

Paul Tarvydas

unread,
Jun 19, 2026, 10:29:18 PMJun 19
to pi...@googlegroups.com

That’s what Software Architecture is for. Trying to generalize the solution (as was done with thread safety) only bloatifies the result.

State isn't actually bad. Reality contains state. State within the FP paradigm is bad, though.

Programming languages based on the synchronous, sequential paradigm (i.e. most current PLs) make the use of state very clunky (global variables, if-then-else, blobs of state passed around as data, etc). That is a "tell" that this issue should be handled in a different notation. I kinda like Harel Statecharts, as previously mentioned.

Languages like Prolog, Datalog, Ceptre, Nova, and concatenative languages are different (non-FP) approaches to the issue of state. Ceptre is based on linear logic. There are many ways of doing this other than by just doing the same thing over and over and expecting different results.

Automagic state coherence is just an inefficient trick that architects should be allowed to choose to use when necessary, instead of having it hard-wired into hardware and programming languages.

aside: SIMD and SIMT are just other automagic tricks that are very optimized for a narrow range of use-cases (graphics, GPUs), but, are just albatrosses around the necks of other use-cases.

The strive for generalization makes us feel that the solution to every conceivable problem must be spoon fed to us. Software Architects should want access to specialization and LEGO-like parts and layers. That's not what we have at this moment. It's within reach, though. It's mostly just a mind-set problem.


On Jun 19, 2026, at 9:48 PM, Raoul Duke <rao...@gmail.com> wrote:

still doesn't fix the core issue of state coherence / consistency 

--
You received this message because you are subscribed to the Google Groups "PiLuD" group.
To unsubscribe from this group and stop receiving emails from it, send an email to pilud+un...@googlegroups.com.
To view this discussion visit https://groups.google.com/d/msgid/pilud/CAJ7XQb6Kyxtw3jELtxXiWjGA%3D%3DDR9LM%2BfaeL4zWx5Hm0s%2BWvHg%40mail.gmail.com.

Raoul Duke

unread,
Jun 20, 2026, 12:50:12 AMJun 20
to pi...@googlegroups.com
We're talking past one another i suspect - i don't care about or laud or overly defend the usual paradigms. But saying they are bad might help remove accidental conplexity but doesn't in and of itself solve some of the core problems they tried to solve. There's essential complexity no matter what. Somebody has to explain how to directly gordian-knot solve THAT stuff. 

Mike Austin

unread,
Jun 27, 2026, 1:27:00 PM (9 days ago) Jun 27
to PiLuD
GraphQL, although a separate language, has helped me tremendously. I can query and join data, filter, sort, etc. at many levels, and the data that comes back doesn't need to be transformed. It's ready to be consumed.
Done correctly, the "reactive" nature is built in -- if I mutate data in one query, it will trigger cache or resource update and cause dependent queries to update. I don't need to trigger any manual refreshes.

  query SelectItems($teamKey: String!) {
    items(where: {
      team: {
        key: {
          _eq: $teamKey
        }
      }
    }, order_by: {
      order: asc
    }) {
      ...ItemFragment
id
tags {
id
label
}
    }
  }
  ${ITEM_FRAGMENT}

This will return data such as {
  items: [
    {
      id: "foo", title: "bar", tags: [
        { id: 0, label: "one" }, { id: 1, label: "two" }
      ]
    },
  ]
}

I'm really glad GraphQL is a thing. The "bad" thing about GraphQL is that table names, property names, sorting, filtering, etc. is not standardized. One company may implement "_eq" for equals, or "equals", for example. Aggregate data is also expressed differently. This creates a kind of "vendor lock in" unless you create an abstraction around it.

David Barbour

unread,
Jun 27, 2026, 10:02:56 PM (9 days ago) Jun 27
to pi...@googlegroups.com
State isn't simply memory or mutation; it is any dependency of the future on the past.

Issues such as coherence and race conditions can appear just as easily with message passing as they do with shared memory. For example, a shared-nothing actor in an actor model can still model a "mutable cell" in memory. You'd still have race conditions between reading and writing these cells.

The patterns of interaction are more relevant than whether those interactions are implemented using threads, actors, or processes. 

Paul Tarvydas

unread,
Jun 28, 2026, 8:37:27 AM (8 days ago) Jun 28
to pi...@googlegroups.com

Thanks. That is a good description...

State isn't simply memory or mutation; it is any dependency of the future on the past. 

Issues such as coherence and race conditions can appear just as easily with message passing as they do with shared memory. For example, a shared-nothing actor in an actor model can still model a "mutable cell" in memory. You'd still have race conditions between reading and writing these cells.

Coherence is not needed most of the time. Premature coherence gives rise to inefficiency and overkill.

There is but only one race condition - when two events A and B arrive "simultaneously", if you can't tell in what order they arrived in, then it's a race condition. All of the other so-called race conditions are accidental complexities created by the use of an inappropriate substrate paradigm.

The patterns of interaction are more relevant than whether those interactions are implemented using threads, actors, or processes.

Agreed. Maybe I'm reading more into what you've written than what you intended, but ... I perceive that our current trend of borrowing from the "functional programming" paradigm (starting with something like C) and wanting to believe that "everything is a computation" is a death march or, at best, a way to exponentially increase accidental complexity. Our use of functions for programming languages is just a convenience. It's a spherical cow that ignores asynchronicity, time and ordering to make some things simpler, but, it cannot - by definition - deal with the totality of Reality. 

I believe that we need ways to reason about state and ordering of events, regardless of how convenient the "everything is just a computation" paradigm is (only for a subset of problem domains, though). Reality is composed of state. We cannot address Reality without addressing state. I note that Nobel laureate Ilya Prigogene said the same thing about the functional approach to physics. In "Order Out of Chaos" he says that this approach has set physics back by 100 years.

aside: our current programming languages allow us to handle state but only in a clunky, low-level way - using global variables and if-then-else, or, bags of state passed around as parameters. Notation is important - language influences thought. Harel showed a notation (Statecharts) for expressing stateful control flow in a more convenient way some 40 years ago. Part of the problem, IMO, is the belief that we should try to use only one language at a time and try to glue everything into that language or invent workarounds to fit the problem into the underlying paradigm of the one language. Programming languages are just caveman IDEs for programming, devised in the early days of programming. If we, instead, had IDEs that allowed us to build solutions by composing snippets of code tuned for each sub-domain (instead of blobs of tangled, work-around-filled code written using General Purpose Languages) we might be able to drastically increase our development turnaround time. (aside to aside: the current belief that using multiple languages is difficult is based on the use of General Purpose Languages instead of more laser-focussed Special Purpose Languages. I know that using multiple languages is not that hard).

Further:
The Spherical Cows of Programming
The Wrong Spherical Cow - First Principles of Parts Based Programming
The Case For Composable Notations (1 / 5) - The Spherical Cow We Forgot We Were Riding
The Case For Composable Notations (2 / 5) - The Restrictions That Came With The Cow
The Case For Composable Notations (3 / 5) - State Isn’t The Enemy
The Case For Composable Notations (4 / 5) - Ease of Expression Is the Whole Point
The Case For Composable Notations (5 / 5) - UNIX Already Showed Us the Way
The Case For Composable Notations (6 / 5) - WIP - Notations in Progress

pt

Raoul Duke

unread,
Jun 28, 2026, 9:02:43 AM (8 days ago) Jun 28
to pi...@googlegroups.com
For me, I think if one does not present an actual calculus for managing state, anything else is handwaving and borderline delusional since we already know how everything else is a fail. Things like MVCC at least try to start off admitting the kernel of truth. 

Paul Tarvydas

unread,
Jun 28, 2026, 10:53:45 AM (8 days ago) Jun 28
to pi...@googlegroups.com
Actually Harel did present a formal way to analyze statecharts in a followup paper (1987, iirc).

pt


On Jun 28, 2026, at 9:02 AM, Raoul Duke <rao...@gmail.com> wrote:

For me, I think if one does not present an actual calculus for managing state, anything else is handwaving and borderline delusional since we already know how everything else is a fail. Things like MVCC at least try to start off admitting the kernel of truth. 


--
You received this message because you are subscribed to the Google Groups "PiLuD" group.
To unsubscribe from this group and stop receiving emails from it, send an email to pilud+un...@googlegroups.com.

David Barbour

unread,
Jun 28, 2026, 2:19:50 PM (8 days ago) Jun 28
to pi...@googlegroups.com
On Sun, Jun 28, 2026 at 7:37 AM Paul Tarvydas <paulta...@gmail.com> wrote:

Coherence is not needed most of the time. Premature coherence gives rise to inefficiency and overkill.

Some form of coherence is needed, but there are weaker and stronger forms of coherence.

Agreed. Maybe I'm reading more into what you've written than what you intended, but ... I perceive that our current trend of borrowing from the "functional programming" paradigm (starting with something like C) and wanting to believe that "everything is a computation" is a death march or, at best, a way to exponentially increase accidental complexity.

Call-return is awkward when it comes to modeling interaction. There are workarounds, such as multi-agent session types, monadic effects, delimited continuations. But something like Yves Lafont's Interaction Calculus (~1990) offers a more explicit foundation for modeling interactive, parallel, distributed systems than Alonzo Church's Lambda Calculus (~1930).

Our use of functions for programming languages is just a convenience. It's a spherical cow that ignores asynchronicity, time and ordering to make some things simpler, but, it cannot - by definition - deal with the totality of Reality.

The closest 'languages' to reality are higher-dimensional cellular automata that have some notions of symmetry aligned to physics, e.g. conservation of 'mass' and 'energy'. They are, simultaneously, the very worst languages to reason about and program in. They make for fun toys, though.

Ultimately, we're responsible for the behavior of our programs. We cannot reason about the behavior of the totality of reality. Thus, there will always be a practical boundary, and some indirection, between program logic and reality. And that boundary will always be based on some decisions of convenience: of reasoning, of composition, of deployment. Convenience is not something to scoff at. Unless you want to 'program' via physics simulations.

But our PLs could support a more-flexible lower-bound on abstraction.

Instead of general purpose application programming languages, where users primarily describe runtime behavior, we could design general purpose assembly languages, where users primarily describe an executable specification. Staged programming, where the output can be any heterogeneous mix of x86 machine code, Kubernetes configurations, hardware description etc.. We can feasibly build our towers of abstraction while simultaneously digging out a deeper basement of abstraction.

Application languages tend to set a lower bound on abstraction that's too high for some problems and too low for others. This results in awkward scenarios where we need different languages for different problems.

A general purpose assembly language won't provide the tools for "composing snippets of code tuned for each sub-domain", but it should provide an environment where such tools - higher-order, modular, adaptable, extensible, robust 'assembly macros' - can be effectively built. There's still quite a gap between, say, Kahn process networks and x86 machine code. A general-purpose assembly would force you to fill that gap explicitly. But you'd never be blocked by someone else's compiler, since you'd control your compiler within the language.  

Notation is important - language influences thought.

I agree. Even arithmetic was difficult to think about with Roman numerals. There are many notations yet undiscovered, and many discovered notations we haven't adequately exploited. Including Lafont's interaction nets and Harel's statecharts.

David Barbour

unread,
Jun 29, 2026, 3:59:18 AM (8 days ago) Jun 29
to pi...@googlegroups.com


On Sun, Jun 28, 2026, 7:37 AM Paul Tarvydas <paulta...@gmail.com> wrote:

There is but only one race condition - when two events A and B arrive "simultaneously", if you can't tell in what order they arrived in, then it's a race condition. All of the other so-called race conditions are accidental complexities created by the use of an inappropriate substrate paradigm.

Focusing on this assertion specifically. It seems biased or privileged to centralized computation. Events "arrived" where?

An important race condition is that different observers may see the same event stream in different orders. By analogy, it'd be like every 'thread group' of a Harel state chart getting a different order of events.

This is mostly a problem for distributed systems. But modern CPUs operate at such a frequency that light is moving less than 10cm per clock cycle. Relativistic light cones are an issue even within a LAN. 
 

Raoul Duke

unread,
Jun 29, 2026, 6:38:57 AM (7 days ago) Jun 29
to pi...@googlegroups.com
seems like the real fundamental is to define a solid reconciliation strategy for when ordering inevitably goes tits-up. 

David Barbour

unread,
Jun 29, 2026, 11:07:59 AM (7 days ago) Jun 29
to pi...@googlegroups.com
The simplest resolution is to insist events, e.g. messages, are processed by only one component. 

Then, no matter what race conditions, there is no *observed* inconsistency. Though, it's also useful to ensure messages *from* any given source are ordered. A numbering sequence can help there.

Paul Tarvydas

unread,
Jun 29, 2026, 4:01:27 PM (7 days ago) Jun 29
to pi...@googlegroups.com

Some form of coherence is needed, but there are weaker and stronger forms of coherence.

"Coherence often means that different parts of a system maintain a consistent view."

My perception is that the prevalent view of coherence (e.g. cache coherence) is too fine-grained for use in distributed systems.

Software architects should design-in coherence only when needed, i.e. through protocols and explicit synchronization. My perception is that our hardware and software insists on providing cache coherence at the expense of efficiency.

pt

Paul Tarvydas

unread,
Jun 29, 2026, 4:03:11 PM (7 days ago) Jun 29
to pi...@googlegroups.com

But something like Yves Lafont's Interaction Calculus (~1990) offers a more explicit foundation for modeling interactive, parallel, distributed systems than 

Thanks. I need to learn more about that.


pt


Paul Tarvydas

unread,
Jun 29, 2026, 4:07:00 PM (7 days ago) Jun 29
to pi...@googlegroups.com

Convenience is not something to scoff at. Unless you want to 'program' via physics simulations.

...


But our PLs could support a more-flexible lower-bound on abstraction.

I believe that the biggest missing ingredient in our programming languages is the notion of "time" (ordering, sequencing). It can be manually expressed in our languages, but, that's not the same as using a notation that treats it as a first-class concept.

pt


Paul Tarvydas

unread,
Jun 29, 2026, 4:10:02 PM (7 days ago) Jun 29
to pi...@googlegroups.com

Focusing on this assertion specifically. It seems biased or privileged to centralized computation. Events "arrived" where?

I'm not sure I understand this point. The idea of events arriving somewhere is biased by a decentralized perspective. I think that that bias towards centralization is something that we got away with in the 20th century but we must move towards a decentralized bias in the next century.


pt


Paul Tarvydas

unread,
Jun 29, 2026, 4:12:59 PM (7 days ago) Jun 29
to pi...@googlegroups.com

An important race condition is that different observers may see the same event stream in different orders. ...

I agree. 

This is mostly a problem for distributed systems. But modern CPUs operate at such a frequency that light is moving less than 10cm per clock cycle. Relativistic light cones are an issue even within a LAN. 

The "C" in CPU means Centralized. We've utilized notations for programming centralized CPUs to the point of overkill.

pt


Paul Tarvydas

unread,
Jun 29, 2026, 4:29:08 PM (7 days ago) Jun 29
to pi...@googlegroups.com

The simplest resolution is to insist events, e.g. messages, are processed by only one component. 

That is indeed simple. But, from a decentralized perspective all you need to do is to ensure atomicity of event delivery to prevent interleaving of events in time. If one adopts an asynchronous event delivery method (fire-and-forget), then this kind of atomicity can be quite cheap for geographically close devices, e.g. inside a single computer vs. spread across continents.

... A numbering sequence can help there.

Another method is to use queues or mailboxes with tagged events. One input queue and one output queue per component. Events are tagged with their port ids and enqueued, in order of arrival and generation, on those queues. It's not as fine-grained as using sequence numbers, but, it opens the door to many interesting, new architectures composed of asynchronous components, such as might be found in electronic schematics, like Atari Pong, 1972 (I'm currently trying to convert that thinking into Parts Based Programming (PBP) software). I find that simply allowing Parts to have multiple inputs and multiple outputs and making Parts asynchronous leads to interesting ideas and architectures more quickly than thinking using overly-synchronous notations.

pt

David Barbour

unread,
Jun 30, 2026, 3:39:11 AM (7 days ago) Jun 30
to pi...@googlegroups.com
On Mon, Jun 29, 2026, 3:01 PM Paul Tarvydas <paulta...@gmail.com> wrote:

"Coherence often means that different parts of a system maintain a consistent view."

Yes. But consistent doesn't mean equivalent. For example, eventual consistency or CRDTs are forms of coherence useful in distributed systems.

My perception is that the prevalent view of coherence (e.g. cache coherence) is too fine-grained for use in distributed systems.

Cache coherence corresponds roughly to mirrored state. It's alright for read-mostly data, and can be coherent in distributed systems with some protocol to authorize update (e.g. ownership or quorum) and wavefront propagation.

But it shouldn't be your only approach to coherence in distributed systems.

For example: dividing reader and writer endpoints of a queue or channel, migration of state to computations (or vice versa), bags or multisets (can be freely partitioned across nodes, opportunistic data transfer), and CRDTs (can be replicated and updated independently across nodes, opportunistic merge). 

These are fairly prevalent approaches to coherence for distributed systems,.

Software architects should design-in coherence only when needed

They're needed only when you reason about stateful program behavior. Which, IMO, is every time you program.

But if your intention is closer to "we shouldn't be stuck with a one-size-fits-most model of coherence, should be able to design whatever we need" then I'm more inclined to agree.

My perception is that our hardware and software insists on providing cache coherence at the expense of efficiency.

Hardware should accelerate what people use. And people should leverage what hardware accelerates. 

There is certainly a form of path dependence and network effects here. Opportunity costs for the paths not taken.

But although the outcome might change, the path dependence itself would be inevitable no matter the 'what if' you throw at it.

Reply all
Reply to author
Forward
0 new messages