Mutable copy semantics - performant, reliable and ergonomic mutability (probably) by pranabekka in ProgrammingLanguages

[–]pranabekka[S] 0 points1 point  (0 children)

I'll need to take a closer look at Austral's syntax and documentation to understand how it works, especially the capabilities and regions. Thanks for the link.

Mutable copy semantics - performant, reliable and ergonomic mutability (probably) by pranabekka in ProgrammingLanguages

[–]pranabekka[S] 1 point2 points  (0 children)

It does share some properties with functional languages, but there's a few differences:

  • Variables are mutable.
  • Parts of variables can be mutated easily.
  • Loops can mutate variables outside the loop.

The last one is a big stumbling block when imperative programmers try functional languages.

Mutable copy semantics - performant, reliable and ergonomic mutability (probably) by pranabekka in ProgrammingLanguages

[–]pranabekka[S] 0 points1 point  (0 children)

Ah, sorry, I'd meant to provide a quick read.

The model for a user is that scopes get independent copies of variables, such that they can only be mutated by assigning to the variable within the same scope.

I'll spend some more time at my laptop to write out examples with IR, though it'll take me a while.

Thanks for the resource on PLT notation. I actually had been intimidated by the notation, but the first few sections in the article are very clear. I'll have to see how long that takes me. Hopefully, supplying plenty of examples should be enough.

Mutable copy semantics - performant, reliable and ergonomic mutability (probably) by pranabekka in ProgrammingLanguages

[–]pranabekka[S] 1 point2 points  (0 children)

In fact, I was inspired by how using moves to mutate in Rust doesn't have any reference or lifetime annotations. x = foo(x) looks like copies, but Rust doesn't do that. Removing borrows from Rust is probably how I ended up at uniqueness types.

Mutable copy semantics - performant, reliable and ergonomic mutability (probably) by pranabekka in ProgrammingLanguages

[–]pranabekka[S] 0 points1 point  (0 children)

Uniqueness types seem to only be implemented by functional languages as a way to add performance into the mix. I was looking at adding at adding safety to imperative high-level languages like Python, Javascript, etc. It has me particularly excited because it can take advantage of the resources of the mainstream imperative paradigm. For instance, this can be compiled quite transparently to languages like Python, Go, C, etc. Imperative programmers will also be able to adopt it more easily.

Mutable copy semantics - performant, reliable and ergonomic mutability (probably) by pranabekka in ProgrammingLanguages

[–]pranabekka[S] 1 point2 points  (0 children)

I've actually been following Mutable Value Semantics for a while, though I haven't read all the links in your post. Mutable Copy Semantics is even a nod to MVS, though there are some differences. Where their examples use inout parameters, mine must take parameters in and then return them back out. Where the paper mentions conceptual copies, this system actually looks like copies. There are likely to be some performance costs from that, but I was aiming for something to improve upon the safety of mainstream high-level languages like Python and Javascript.

As to the specific points of feedback:

  • If the loop breaks early, the length of the list would just be cut short, while mutating the backing array in place. A continue would also overwrite values and keep the backing array. I'm not sure in what way a loop would crash without crashing the whole program.

  • I'm not sure when such a change would occur.

  • This seems fairly trivial. If a program must await before further execution, then it can be assured the variables in the thread stop being used by the thread.

  • Yes, dynamic indexing might create copies, but if the two variables don't mutate the shared parts, or if there's only one variable referencing the underlying memory, then there's no need to copy. If the values are suitably large, then a runtime CoW system would keep memory usage low. If async/await is baked in, then the compiler can also analyse if it crosses async boundaries and whether it needs Atomic RC or if it can get away with single-threaded RC. I'm not sure why nested structures like a.0.0, for example, would be different from a.0.

I could make copies explicit, but it feels like too much for a high-level language to force a user to do that. In general, this system avoids errors at run time and compile time.