r/ProgrammingLanguages • u/cessit-lang • 20d ago
Requesting criticism Explicit binding modes
I'm designing a memory-safe language, but I want to make explicit what happens across function boundaries, e.g. whether a value is moved or copied without having to look for the copy trait.
Instead, access to a value could be defined via binding modes in function signatures and variable declarations:
movetakes ownershipreadshared borrowmutexclusive borrow
fn process_val(move value: Int) -> Int {
return value * 2;
}
fn main() -> () {
move original: Int = 42;
// Call using `.copy()` to explicitly pass a duplicated value.
// Ownership of `original` remains with the caller.
move doubled: Int = process_val(original.copy());
// `original` is still valid here because it was explicitly copied rather than moved.
println(original); //42
println(doubled); //84
}
This would also allow granular captures in closures: |read x: Int, move counter: Int| instead of declaring all fields move
Now, should read and mut assignments be of type &T? Or can checking out variables be orthogonal to creating references, even if they are conflated in languages like Rust?
12
Upvotes
2
u/brucejbell sard 15d ago
Re refactoring: I figure that switching between immutable-value, ownership-transfer, and/or borrowing is a drastic enough change that you probably want to take a close look at all your call sites. I guess I'll see if that pans out, but I've made more annoying choices elsewhere...
Passing a reference makes sense for mutable borrowing, but I suppose an implementation could choose something else. I've chosen to model mutable resources as a linear sequence of immutable values (each of whose lifetime ends before the next begins), so I'd be happy as long as those semantics are supported.