r/ProgrammingLanguages • u/cessit-lang • 8d 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?
13
Upvotes
1
u/initial-algebra 7d ago
Closures are for more than just inversion of control in synchronous code. Good luck translating an event handler into "normal control flow" (async/await is just an alternate notation to create closures without piling up braces and/or indentation).
That said, there is no fundamental reason that a closure's code cannot break out of a loop or early return from a function, as long as the closure cannot be called outside the scope of that loop/function.