Rendered at 17:53:27 GMT+0000 (Coordinated Universal Time) with Cloudflare Workers.
mayoff 22 hours ago [-]
This article is about actors in the Swift programming language, and I’d answer the question (“is a stateless actor pointless?”) differently: there is no such thing as a stateless actor in Swift.
Every actor in Swift conforms to the Actor protocol, which has one requirement: an instance property named `unownedExecutor`. Swift uses this property implicitly when, for example, the program calls a method on the actor from outside the actor.
(One could also argue that, because every actor type is a reference type, every actor also has its identity as part of its state.)
Suppafly 16 hours ago [-]
>This article is about actors in the Swift programming language
Glad I checked the comments first, I had assumed it was stateless people that were actors. Stateless people are kind of an interesting topic.
Nevermark 9 hours ago [-]
There is no language (yet) which makes fine-tuned for-purpose abstractions, of all familiar kinds, both trivial to specify and performant to run/compile.
So anyone coding anything interesting is almost certainly under or over using their languages' and libraries' abstractions.
Also, for highly composable languages, where null versions of almost anything make sense: Stateless states, operationless operations, destinationless network ports, storage roots not associated with any hardware, just "0 bytes", ... all make practical sense.
_tk_ 21 hours ago [-]
You mean APTs that are not state sponsored…? Oh.
hackyhacky 21 hours ago [-]
No, this is an article about immutable thespians.
mrkeen 24 hours ago [-]
A race condition:
Two processes intend to add two to a number.
They each read the current value.
Then they each write back the value which is two bigger then the original.
If you instead use private fields and public getters/setters, or use actors to form a protective bubble around the mutable state, you get...
The exact same thing but with more boilerplate.
hackyhacky 22 hours ago [-]
The key feature of Erlang-style actors is that messages are enqueued and processed serially, thus eliminating race conditions of this type.
layer8 22 hours ago [-]
If the read and the write are separate messages, i.e. the computation of the modified value happens sender-side, as in the parent example, then I don’t see how a serializing queue prevents the race condition, for two concurrent senders (clients). For that you need transactions, exactly like a database.
hackyhacky 22 hours ago [-]
That's not how you would implement mutating messages in an actor system. Instead you could do either of these:
* Have an "increment" message that adds n to the current value and returns the old value.
* Have separate "read" and "write" messages, where the "write" message is parameterized by a timestamp returned by the "read" message. If the owner detects that the timestamp sent by the write is older than the most recent timestamp, it's rejected.
Because messages are handled serially, it's easy and safe to create messages that behave sanely event without explicit locks.
mrkeen 21 hours ago [-]
You wouldn't implement the "plus 2" program in an actor system this way, because of race conditions.
Same as you wouldn't implement the "plus 2" program in an OO, functional, or this way, because of race conditions.
Either way, it's up to programmer discipline.
hackyhacky 21 hours ago [-]
> You wouldn't implement the "plus 2" program in an actor system this way, because of race conditions.
Can you explain how a serially-executed "increment" message in an actor system, as I've described above, would cause a race condition?
In an OOP system you could do the same, you'd just have to build the thread-safe message queue yourself. In actor languages it's built in.
There are cases where you can get race conditions in actor languages, but I'm pretty sure this isn't one.
layer8 7 hours ago [-]
The point is that you have to implement it in the specific ways you describe in order to prevent a race condition. The actor model doesn’t eliminate race conditions by itself. This is true in all programming models. A database also doesn’t eliminate race conditions, you have to use appropriate transactions in order to prevent them. What you describe for the actor model is virtually the same thing: you have to use transactional messages in order to prevent race conditions. And that doesn’t happen by itself, the programmer has to implement the program logic in that specific way. There is no magic silver bullet.
hackyhacky 6 hours ago [-]
> There is no magic silver bullet.
Did someone claim otherwise?
> The actor model doesn’t eliminate race conditions by itself.
Sure, and the actor model was never marketed as "a tool to eliminate race conditions." That's not what it's for.
You have to use your tools correctly. One benefit of the actor model is that the tool eliminates large categories of race conditions (but not all of them). One benefit of garbage collection is that the tool eliminates large categories of memory errors (but not all of them). The same can be said of anything, from high-level languages, to debuggers, to linters, the IDEs, etc. Just because a tool is not a "silver bullet" does not mean that it does not deliver a strong advantage for the programmer.
mrkeen 21 hours ago [-]
This is correct, but databases only help to the extent that the whole world is happy to live in your database.
As soon as you have customers (who interact via REST), or partner payment systems (e.g. stripe) you're back to:
Two customers do a GET. This gets dispatched to the DB, wrapped in a nice transaction, the transaction ends, the customers get their result.
The two customers then do a POST to set a new value. Also wrapped in a transaction.
Race condition with more steps.
hackyhacky 20 hours ago [-]
As I pointed out above, that's not the API that would be exposed in an actor model. See in particular the timestamp-based update condition, if you're principally concerned with end-user-caused races.
Less relevant, but message queues in Erlang and related languages are typically in-memory, no DB transaction required.
Every actor in Swift conforms to the Actor protocol, which has one requirement: an instance property named `unownedExecutor`. Swift uses this property implicitly when, for example, the program calls a method on the actor from outside the actor.
https://developer.apple.com/documentation/swift/actor/unowne...
(One could also argue that, because every actor type is a reference type, every actor also has its identity as part of its state.)
Glad I checked the comments first, I had assumed it was stateless people that were actors. Stateless people are kind of an interesting topic.
So anyone coding anything interesting is almost certainly under or over using their languages' and libraries' abstractions.
Also, for highly composable languages, where null versions of almost anything make sense: Stateless states, operationless operations, destinationless network ports, storage roots not associated with any hardware, just "0 bytes", ... all make practical sense.
The exact same thing but with more boilerplate.
* Have an "increment" message that adds n to the current value and returns the old value.
* Have separate "read" and "write" messages, where the "write" message is parameterized by a timestamp returned by the "read" message. If the owner detects that the timestamp sent by the write is older than the most recent timestamp, it's rejected.
Because messages are handled serially, it's easy and safe to create messages that behave sanely event without explicit locks.
Same as you wouldn't implement the "plus 2" program in an OO, functional, or this way, because of race conditions.
Either way, it's up to programmer discipline.
Can you explain how a serially-executed "increment" message in an actor system, as I've described above, would cause a race condition?
In an OOP system you could do the same, you'd just have to build the thread-safe message queue yourself. In actor languages it's built in.
There are cases where you can get race conditions in actor languages, but I'm pretty sure this isn't one.
Did someone claim otherwise?
> The actor model doesn’t eliminate race conditions by itself.
Sure, and the actor model was never marketed as "a tool to eliminate race conditions." That's not what it's for.
You have to use your tools correctly. One benefit of the actor model is that the tool eliminates large categories of race conditions (but not all of them). One benefit of garbage collection is that the tool eliminates large categories of memory errors (but not all of them). The same can be said of anything, from high-level languages, to debuggers, to linters, the IDEs, etc. Just because a tool is not a "silver bullet" does not mean that it does not deliver a strong advantage for the programmer.
As soon as you have customers (who interact via REST), or partner payment systems (e.g. stripe) you're back to:
Race condition with more steps.Less relevant, but message queues in Erlang and related languages are typically in-memory, no DB transaction required.