Ownership System
JOEL features a Rust-inspired ownership system that provides memory safety without garbage collection in compiled mode.
Ownership Basics
In [Compiled] mode, JOEL uses ownership semantics to manage memory:
[Compiled]
let x = 10 # x owns the value 10
let y = x # y gets a copy (for primitive types)Move Semantics
Complex types use move semantics:
[Compiled]
let list1 = [1, 2, 3]
let list2 = list1 # list1 is moved to list2
# list1 is no longer accessibleBorrowing
Borrowing allows temporary access without taking ownership:
[Compiled]
fn process(data: &list[i32]) {
# data is borrowed, not moved
print(data.len())
}
let my_list = [1, 2, 3]
process(&my_list) # my_list is still accessibleMutable Borrows
Mutable borrows allow modification:
[Compiled]
fn modify(data: &mut list[i32]) {
data.push(4)
}
let mut my_list = [1, 2, 3]
modify(&mut my_list)
print(my_list) # [1, 2, 3, 4]Ownership Rules
- Each value has one owner
- Only one mutable borrow at a time
- Multiple immutable borrows are allowed
- Borrows cannot outlive the owner
Examples
Valid Ownership
[Compiled]
let x = 10
let y = x # Copy for primitives
print(x, y) # Both accessibleInvalid Ownership
[Compiled]
let list1 = [1, 2, 3]
let list2 = list1 # Move
print(list1) # Error: list1 was movedBorrowing Example
[Compiled]
fn sum(numbers: &list[i32]) -> i32 {
let mut total = 0
for n in numbers {
total += n
}
return total
}
let data = [1, 2, 3, 4, 5]
let result = sum(&data) # data is borrowed
print(data) # data is still accessibleOwnership in Functions
Functions can take ownership or borrow:
[Compiled]
# Takes ownership
fn consume(data: list[i32]) {
# data is moved here
}
# Borrows
fn inspect(data: &list[i32]) {
# data is borrowed
}
# Mutable borrow
fn mutate(data: &mut list[i32]) {
# data can be modified
}Ownership and Scopes
Ownership is tied to scope:
[Compiled]
{
let x = 10
# x is owned in this scope
}
# x is dropped hereBest Practices
- Use borrowing when possible - Avoid unnecessary moves
- Prefer immutable borrows - Safer and more flexible
- Use moves for ownership transfer - When you need to take ownership
- Keep scopes small - Allows early cleanup