Hello I did not mention GO out of context in my previous emails. I would like to know the opinion of this forum about what would be the most likely CL - portable - substitute to implement *channels*. *usocket *and/or *bordeaux-threads* are what I'd target. In GO you have *chan *items and you can send and receive from them using the *<-* operator. AFAIU these channels are blocking. Any suggestions? Thanks Happy Holidays Marco -- Marco Antoniotti, Professor, Director tel. +39 - 02 64 48 79 01 DISCo, University of Milan-Bicocca U14 2043 http://dcb.disco.unimib.it Viale Sarca 336 I-20126 Milan (MI) ITALY REGAINS: https://regains.disco.unimib.it/
Any suggestions?
Transactional Conventional Hewitt Actors (staged SEND, BECOME, CREATE until successful exit) https://github.com/dbmcclain/Lisp-Actors
Automatic parallelism through parallel concurrent execution by dispatch thread pool. No user level threads, locks, no shared mutable memory. A convention of functionally pure programming protects concurrent access during parallel execution. Only one overt mutation (BECOME), under carefully controlled CAS execution, with automatic message re-delivery on failed CAS. Asynchronous execution.
On Dec 22, 2025, at 09:52, David McClain <dbm@refined-audiometrics.com> wrote:
Any suggestions?
Transactional Conventional Hewitt Actors (staged SEND, BECOME, CREATE until successful exit)
On Mon, Dec 22, 2025, 8:53 AM David McClain <dbm@refined-audiometrics.com> wrote:
This is very interesting! But I think it needs FSet ( https://github.com/slburson/fset) to store the state of an actor, and make it easy to efficiently compute a new state which can be supplied to BECOME. -- Scott
Interesting suggestion… BECOME takes a functional closure, which contains its state within the closure vars. But I have become frustrated with too many BOA args, and I also implemented a kind of dictionary to carry state with items labeled by a keyword. But there are no rules, just conventions, used within my current Actors system. One convention is to provide a customer (Actor) argument in most messages. But again, no hard rules, just conventions. The most compelling advance from Conventional Hewitt Actors is the notion of transactional behavior which dictates that no SEND nor BECOME can be seen by anyone, including the issuer, until the behavior function exits cleanly. When parallel concurrent execution occurs, only one thread will succeed in committing the SENDS and BECOME. The others will be silently retried by redelivering their message to the (possibly now changed) Actor behavior. Writing code in such a system is a lot like assembling little Leggo blocks of behavior that can be stitched together to provide larger customizable behaviors to the outside world. Currently our hardware is aimed directly at Call/Return function behaviors, and so an Actors-all-the-way-down would be completely impractical on our present computers. I find Call-Return to be effective for the innards of math functions, and Actors to be most practical for high-level orchestration of components - as in the Async Socket interface.
On Dec 22, 2025, at 12:11, Scott L. Burson <Scott@sympoiesis.com> wrote:
On Mon, Dec 22, 2025, 8:53 AM David McClain <dbm@refined-audiometrics.com <mailto:dbm@refined-audiometrics.com>> wrote:
This is very interesting! But I think it needs FSet (https://github.com/slburson/fset) to store the state of an actor, and make it easy to efficiently compute a new state which can be supplied to BECOME.
-- Scott
BECOME takes a functional closure, which contains its state within the closure vars. But I have become frustrated with too many BOA args, and I also implemented a kind of dictionary to carry state with items labeled by a keyword.
Keyword args are a possibility too, but that implies a piling up of old data behind the newly specified keyword arg. And that’s why I implemented the dictionary methods - to prevent keeping stale data from the GC.
On Mon, Dec 22, 2025, 12:20 PM David McClain <dbm@refined-audiometrics.com> wrote:
BECOME takes a functional closure, which contains its state within the closure vars. But I have become frustrated with too many BOA args, and I also implemented a kind of dictionary to carry state with items labeled by a keyword.
Right. I saw your file 'actor-state.lisp' and thought "Ah! This is a functional map. This man needs FSet." Yes, the state is in the closure vars, but that doesn't preclude it being large and complex. With functional data structures, you can efficiently prepare an updated version of a large structure without invalidating the previous version. If something goes wrong before the BECOME takes effect, no harm has been done; the tentative new version simply becomes garbage. The trick is to use only O(log n) space each time, where n is the size of the previous version. -- Scott
Yes, good points O(log n) cost. But that implies that elements have an ordering relation, no? Partial or total order. I have such structures that I use often, red-black trees that are purely functional implementations. So I understand your points here. But many times my data does not have any order relation, just an equality.
On Dec 22, 2025, at 15:52, Scott L. Burson <Scott@sympoiesis.com> wrote:
On Mon, Dec 22, 2025, 12:20 PM David McClain <dbm@refined-audiometrics.com <mailto:dbm@refined-audiometrics.com>> wrote:
BECOME takes a functional closure, which contains its state within the closure vars. But I have become frustrated with too many BOA args, and I also implemented a kind of dictionary to carry state with items labeled by a keyword.
Right. I saw your file 'actor-state.lisp' and thought "Ah! This is a functional map. This man needs FSet."
Yes, the state is in the closure vars, but that doesn't preclude it being large and complex. With functional data structures, you can efficiently prepare an updated version of a large structure without invalidating the previous version. If something goes wrong before the BECOME takes effect, no harm has been done; the tentative new version simply becomes garbage. The trick is to use only O(log n) space each time, where n is the size of the previous version.
-- Scott
I guess the specific example of my Actor-State does have an ordering relation, since the keys are all keyword symbols. So good point on that O(log n). My simple implementation is just a copy / replace, which is O(n).
On Dec 22, 2025, at 17:16, David McClain <dbm@refined-audiometrics.com> wrote:
Yes, good points O(log n) cost. But that implies that elements have an ordering relation, no? Partial or total order. I have such structures that I use often, red-black trees that are purely functional implementations. So I understand your points here. But many times my data does not have any order relation, just an equality.
On Dec 22, 2025, at 15:52, Scott L. Burson <Scott@sympoiesis.com> wrote:
On Mon, Dec 22, 2025, 12:20 PM David McClain <dbm@refined-audiometrics.com <mailto:dbm@refined-audiometrics.com>> wrote:
BECOME takes a functional closure, which contains its state within the closure vars. But I have become frustrated with too many BOA args, and I also implemented a kind of dictionary to carry state with items labeled by a keyword.
Right. I saw your file 'actor-state.lisp' and thought "Ah! This is a functional map. This man needs FSet."
Yes, the state is in the closure vars, but that doesn't preclude it being large and complex. With functional data structures, you can efficiently prepare an updated version of a large structure without invalidating the previous version. If something goes wrong before the BECOME takes effect, no harm has been done; the tentative new version simply becomes garbage. The trick is to use only O(log n) space each time, where n is the size of the previous version.
-- Scott
Actor-State is just an experimental implementation at this time. There are only a few example where I tried using a formal Actor-State. One of them is my implementation of a Key-Value store (kvdb). The other place is in my Ionosphere monitoring system where I track 15 MHz carriers to <100 μHz precision. I did this implementation because a friend of mine involved in Actors machines suggested the JavaScript JSON Dictionary - which I find to be enormously redundant and noisy. Just a simple PList with keyword keys could fully replace them and great simplification. And so my Actor-State was an attempt to prove that out. I fear that Purely Functional Red-Black Trees would be even more costly, but maybe not. I should look into it, or your FSet.
On Dec 22, 2025, at 17:19, David McClain <dbm@refined-audiometrics.com> wrote:
I guess the specific example of my Actor-State does have an ordering relation, since the keys are all keyword symbols. So good point on that O(log n). My simple implementation is just a copy / replace, which is O(n).
On Dec 22, 2025, at 17:16, David McClain <dbm@refined-audiometrics.com> wrote:
Yes, good points O(log n) cost. But that implies that elements have an ordering relation, no? Partial or total order. I have such structures that I use often, red-black trees that are purely functional implementations. So I understand your points here. But many times my data does not have any order relation, just an equality.
On Dec 22, 2025, at 15:52, Scott L. Burson <Scott@sympoiesis.com> wrote:
On Mon, Dec 22, 2025, 12:20 PM David McClain <dbm@refined-audiometrics.com <mailto:dbm@refined-audiometrics.com>> wrote:
BECOME takes a functional closure, which contains its state within the closure vars. But I have become frustrated with too many BOA args, and I also implemented a kind of dictionary to carry state with items labeled by a keyword.
Right. I saw your file 'actor-state.lisp' and thought "Ah! This is a functional map. This man needs FSet."
Yes, the state is in the closure vars, but that doesn't preclude it being large and complex. With functional data structures, you can efficiently prepare an updated version of a large structure without invalidating the previous version. If something goes wrong before the BECOME takes effect, no harm has been done; the tentative new version simply becomes garbage. The trick is to use only O(log n) space each time, where n is the size of the previous version.
-- Scott
On Mon, Dec 22, 2025, 4:21 PM David McClain <dbm@refined-audiometrics.com> wrote: I guess the specific example of my Actor-State does have an ordering relation, since the keys are all keyword symbols. Oh, an ordering relation can be defined for almost anything. FSet has a generic function 'compare' that can be easily extended for new types. Functional red-black trees are a fine choice. FSet has long used an older kind of balanced trees, called weight-balanced. More recently, I've added a relatively new hash-based data structure called CHAMP. On Mon, Dec 22, 2025, 4:25 PM David McClain <dbm@refined-audiometrics.com> wrote:
I track 15 MHz carriers to <100 μHz precision.
Impressive! I did this implementation because a friend of mine involved in Actors
machines suggested the JavaScript JSON Dictionary - which I find to be enormously redundant and noisy. Just a simple PList with keyword keys could fully replace them and great simplification. And so my Actor-State was an attempt to prove that out.
I fear that Purely Functional Red-Black Trees would be even more costly, but maybe not. I should look into it, or your FSet.
Haha, if you want small and simple, FSet might not be to your taste. My goal was to make it easy to use and featureful. It's pretty fast, though. -- Scott
On Dec 22, 2025, at 17:19, David McClain <dbm@refined-audiometrics.com> wrote:
I guess the specific example of my Actor-State does have an ordering relation, since the keys are all keyword symbols. So good point on that O(log n). My simple implementation is just a copy / replace, which is O(n).
On Dec 22, 2025, at 17:16, David McClain <dbm@refined-audiometrics.com> wrote:
Yes, good points O(log n) cost. But that implies that elements have an ordering relation, no? Partial or total order. I have such structures that I use often, red-black trees that are purely functional implementations. So I understand your points here. But many times my data does not have any order relation, just an equality.
On Dec 22, 2025, at 15:52, Scott L. Burson <Scott@sympoiesis.com> wrote:
On Mon, Dec 22, 2025, 12:20 PM David McClain <dbm@refined-audiometrics.com> wrote:
BECOME takes a functional closure, which contains its state within the closure vars. But I have become frustrated with too many BOA args, and I also implemented a kind of dictionary to carry state with items labeled by a keyword.
Right. I saw your file 'actor-state.lisp' and thought "Ah! This is a functional map. This man needs FSet."
Yes, the state is in the closure vars, but that doesn't preclude it being large and complex. With functional data structures, you can efficiently prepare an updated version of a large structure without invalidating the previous version. If something goes wrong before the BECOME takes effect, no harm has been done; the tentative new version simply becomes garbage. The trick is to use only O(log n) space each time, where n is the size of the previous version.
-- Scott
But perhaps you meant mainly to suggest FSET as a method for avoiding shared mutable data? There should never be open mutation, even of the closure data. The safety of fully parallel concurrency can only be guaranteed by performing all mutations through BECOME which relies on a CAS operation in the dispatch threads. I suppose you could get around that restriction with FSET. But then so could you with LOCKS and SEMAPHORES and all the other SMP primitives. Right now, as long as you abide by functional coding and BECOME as the only mutator, we can completely dispense with LOCKS, THREADS, SEMAPHORES, MAILBOXES. None of that is necessary at the user programmer level. You code as though you are the sole occupant of the machine. And so long as you abide by clean conventions, fully parallel concurrency is yours. The same code runs as well in a single thread, or on multiple cores and threads. Speed of execution is the only variable.
On Dec 22, 2025, at 12:11, Scott L. Burson <Scott@sympoiesis.com> wrote:
On Mon, Dec 22, 2025, 8:53 AM David McClain <dbm@refined-audiometrics.com <mailto:dbm@refined-audiometrics.com>> wrote:
This is very interesting! But I think it needs FSet (https://github.com/slburson/fset) to store the state of an actor, and make it easy to efficiently compute a new state which can be supplied to BECOME.
-- Scott
But perhaps you meant mainly to suggest FSET as a method for avoiding shared mutable data? There should never be open mutation, even of the closure data. The safety of fully parallel concurrency can only be guaranteed by performing all mutations through BECOME which relies on a CAS operation in the dispatch threads.
I suppose you could get around that restriction with FSET. But then so could you with LOCKS and SEMAPHORES and all the other SMP primitives.
Right now, as long as you abide by functional coding and BECOME as the only mutator, we can completely dispense with LOCKS, THREADS, SEMAPHORES, MAILBOXES. None of that is necessary at the user programmer level. You code as though you are the sole occupant of the machine. And so long as you abide by clean conventions, fully parallel concurrency is yours.
The same code runs as well in a single thread, or on multiple cores and threads. Speed of execution is the only variable.
This is a fairly narrow mode of operation, where a task can functionally produce an output that gets committed with a single atomic operation. Most often, (green or SMP) threads are used when an operation must naturally interleave computation with mutation of shared structures and I/O. -- Stelian Ionescu
Am 22.12.2025 um 17:52 schrieb David McClain <dbm@refined-audiometrics.com>:
Any suggestions?
Transactional Conventional Hewitt Actors (staged SEND, BECOME, CREATE until successful exit)
Or maybe Sento (https://github.com/mdbergmann/cl-gserver).
Am 22.12.2025 um 22:16 schrieb Manfred Bergmann <manfred.bergmann@me.com>:
Am 22.12.2025 um 17:52 schrieb David McClain <dbm@refined-audiometrics.com>:
Any suggestions?
Transactional Conventional Hewitt Actors (staged SEND, BECOME, CREATE until successful exit)
Or maybe Sento (https://github.com/mdbergmann/cl-gserver).
Although Chanl or lparallel are probably the most Go idiomatic solutions.
There is a quite old library called chanl that has similar semantics. Worked well for me. Am 22. Dezember 2025 17:26:24 MEZ schrieb Marco Antoniotti <marco.antoniotti@unimib.it>:
Hello
I did not mention GO out of context in my previous emails.
I would like to know the opinion of this forum about what would be the most likely CL - portable - substitute to implement *channels*. *usocket *and/or *bordeaux-threads* are what I'd target.
In GO you have *chan *items and you can send and receive from them using the *<-* operator. AFAIU these channels are blocking.
Any suggestions?
Thanks
Happy Holidays
Marco
-- Marco Antoniotti, Professor, Director tel. +39 - 02 64 48 79 01 DISCo, University of Milan-Bicocca U14 2043 http://dcb.disco.unimib.it Viale Sarca 336 I-20126 Milan (MI) ITALY
REGAINS: https://regains.disco.unimib.it/
participants (7)
-
David McClain -
Manfred Bergmann -
Marco Antoniotti -
Pascal Costanza -
Scott L. Burson -
Stelian Ionescu -
Svante v. Erichsen