Comparison: Move Semantics
Value Passing
OCaml โ values are shared via GC:
๐ช Show OCaml equivalent
let use_string s =
Printf.printf "Using: %s\n" s;
String.length s
let () =
let greeting = "Hello!" in
let _ = use_string greeting in
let _ = use_string greeting in (* fine โ GC manages it *)
()
Rust โ values are moved (consumed):
fn use_string(s: String) -> usize {
println!("Using: {}", s);
s.len()
}
fn main() {
let greeting = String::from("Hello!");
let _ = use_string(greeting);
// let _ = use_string(greeting); // ERROR: moved
}
Keeping Both Copies
OCaml โ automatic, no action needed:
๐ช Show OCaml equivalent
let a = [1; 2; 3] in
let b = a in (* both a and b point to same list *)
assert (a = b)
Rust โ explicit clone required:
let a = vec![1, 2, 3];
let b = a.clone(); // explicit copy
// let b = a; // this would MOVE, making a invalid
assert_eq!(a, b);
Simulating Move in OCaml
OCaml โ manual protocol with option ref:
๐ช Show OCaml equivalent
let take (slot : string option ref) =
match !slot with
| Some s -> slot := None; s
| None -> failwith "already moved"
Rust โ built into the language:
let mut opt = Some(String::from("data"));
let taken = opt.take(); // Option::take moves out
assert!(opt.is_none());
Copy Types
OCaml โ everything is "copy-like" (GC-managed):
๐ช Show OCaml equivalent
let x = 42 in
let y = x in (* both valid, always *)
Rust โ only `Copy` types avoid move:
let x: i32 = 42;
let y = x; // Copy, not move โ both valid
let s = String::from("hi");
let t = s; // Move! s is invalid now