I think he has a point, but I also think that's not the end of it.
If my experiments are correct, it's possible to turn a tree of ownership, which is linear, into a directed acyclic graph (DAG), which I hope is non-linear.
Here's how:
1. Use structured concurrency for your ownership model, which creates a tree of threads.
2. Extend the "tree" of threads to include each function on the stack as a node.
3. When you need to "create" an edge between two nodes in your tree, which means sharing data in some way that might violate ownership semantics, have one thread ("A") ask the other ("B") to provide a weak, non-owned reference, while it gives a "token" in return. B may implement this however it likes, but it could give a reference to a new child thread that it will then wait on.
4. When A gets the reference, it runs a function to do the work it needs to do with that reference.
5. When B gets the token, which it owns, it executes as far as it can before trying to "destroy" the token.
6. The token will "wait" on A to finish using the reference that B gave to A. This will mean waiting until the function that A executed with the reference returns. How this is implemented doesn't matter (semaphore?), but basically, the token forces B to wait until A is done with the data.
This creates a DAG like this:
O
|
O
|
O
/ \
A B
| |
A B
| |
A B'
|\ |
A'\ |
| \|
A' B''
where the data is created in B', but A gets it from B'', which has to wait until A' is done executing.
The question then becomes: is it always possible to do what A needs to do by calling a function?
The answer is yes because any function by itself is Turing-complete.
You do need to structure the code to do this, by doing something I call "pushing computation down the stack," but it is possible.
Of course, if a DAG is linear, then this idea of mine won't work. People less ignorant than me will have to say whether a DAG is linear or not.
If my experiments are correct, it's possible to turn a tree of ownership, which is linear, into a directed acyclic graph (DAG), which I hope is non-linear.
Here's how:
1. Use structured concurrency for your ownership model, which creates a tree of threads.
2. Extend the "tree" of threads to include each function on the stack as a node.
3. When you need to "create" an edge between two nodes in your tree, which means sharing data in some way that might violate ownership semantics, have one thread ("A") ask the other ("B") to provide a weak, non-owned reference, while it gives a "token" in return. B may implement this however it likes, but it could give a reference to a new child thread that it will then wait on.
4. When A gets the reference, it runs a function to do the work it needs to do with that reference.
5. When B gets the token, which it owns, it executes as far as it can before trying to "destroy" the token.
6. The token will "wait" on A to finish using the reference that B gave to A. This will mean waiting until the function that A executed with the reference returns. How this is implemented doesn't matter (semaphore?), but basically, the token forces B to wait until A is done with the data.
This creates a DAG like this:
where the data is created in B', but A gets it from B'', which has to wait until A' is done executing.The question then becomes: is it always possible to do what A needs to do by calling a function?
The answer is yes because any function by itself is Turing-complete.
You do need to structure the code to do this, by doing something I call "pushing computation down the stack," but it is possible.
Of course, if a DAG is linear, then this idea of mine won't work. People less ignorant than me will have to say whether a DAG is linear or not.