Skip to content

Commit c42acbc

Browse files
committed
Switching machines.
1 parent 5ea7141 commit c42acbc

File tree

2 files changed

+163
-0
lines changed

2 files changed

+163
-0
lines changed
Binary file not shown.

presentations/2025-11-10-local-reasoning-rs/src/main.rs

Lines changed: 163 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,170 @@
44
fn f(x: i32) -> i32 {
55
x + 1
66
}
7+
#[derive(Debug)]
8+
struct Point {
9+
x: i32,
10+
y: i32,
11+
}
12+
13+
// Return references to two different fields
14+
fn split_coords(p: &mut Point) -> (&mut i32, &mut i32) {
15+
(&mut p.x, &mut p.y)
16+
}
17+
18+
// Can also return just one field
19+
fn get_x(p: &mut Point) -> &mut i32 {
20+
&mut p.x
21+
}
22+
23+
// An iterator that holds a mutable slice and returns non-overlapping mutable references
24+
// This is SAFE because we progressively consume the slice using split_first_mut()
25+
struct OddMutIterator<'a> {
26+
// We hold a mutable slice (not Vec) that we progressively consume
27+
slice: &'a mut [i32],
28+
at_even_index: bool,
29+
}
30+
31+
impl<'a> OddMutIterator<'a> {
32+
fn new(slice: &'a mut [i32]) -> Self {
33+
OddMutIterator {
34+
slice,
35+
at_even_index: true, // Start at index 0 (even)
36+
}
37+
}
38+
}
39+
40+
// Implement Iterator - this yields mutable references to odd-indexed elements
41+
impl<'a> Iterator for OddMutIterator<'a> {
42+
type Item = &'a mut i32;
43+
44+
fn next(&mut self) -> Option<Self::Item> {
45+
loop {
46+
// split_first_mut() is SAFE - it splits the slice into non-overlapping parts:
47+
// - first: &mut T (the first element)
48+
// - rest: &mut [T] (the remaining elements)
49+
// The borrow checker knows these don't overlap!
50+
51+
// We need to use mem::replace to swap out the slice while holding a borrow
52+
let slice = std::mem::replace(&mut self.slice, &mut []);
53+
let (first, rest) = slice.split_first_mut()?;
54+
self.slice = rest; // Consume the first element
55+
56+
if self.at_even_index {
57+
// We're at an even index, skip this element
58+
self.at_even_index = false;
59+
} else {
60+
// We're at an odd index, return this element
61+
self.at_even_index = true;
62+
return Some(first);
63+
}
64+
}
65+
}
66+
}
67+
68+
fn demonstrate_mut_iterator() {
69+
println!("=== Safe iterator using slice splitting ===");
70+
let mut numbers = vec![0, 1, 2, 3, 4, 5, 6, 7];
71+
72+
// Create an iterator that visits odd indices (1, 3, 5, 7)
73+
// We pass a mutable slice, not a Vec
74+
let iter = OddMutIterator::new(&mut numbers[..]);
75+
76+
// Modify each odd-indexed element by multiplying by 10
77+
for elem in iter {
78+
*elem *= 10;
79+
}
80+
81+
// numbers is now [0, 10, 2, 30, 4, 50, 6, 70]
82+
println!("After modifying odd indices: {:?}", numbers);
83+
assert_eq!(numbers, vec![0, 10, 2, 30, 4, 50, 6, 70]);
84+
}
85+
86+
// ========== Bonus: Alternative using split_at_mut for chunks ==========
87+
88+
// An iterator that returns mutable references to pairs of elements
89+
struct PairsMutIterator<'a> {
90+
slice: &'a mut [i32],
91+
}
92+
93+
impl<'a> PairsMutIterator<'a> {
94+
fn new(slice: &'a mut [i32]) -> Self {
95+
PairsMutIterator { slice }
96+
}
97+
}
98+
99+
impl<'a> Iterator for PairsMutIterator<'a> {
100+
type Item = (&'a mut i32, &'a mut i32);
101+
102+
fn next(&mut self) -> Option<Self::Item> {
103+
if self.slice.len() < 2 {
104+
return None;
105+
}
106+
107+
// split_at_mut is also SAFE - splits at an index into two non-overlapping slices
108+
let slice = std::mem::replace(&mut self.slice, &mut []);
109+
let (pair, rest) = slice.split_at_mut(2);
110+
self.slice = rest;
111+
112+
// split_at_mut again to get two non-overlapping mutable references
113+
let (first, second) = pair.split_at_mut(1);
114+
Some((&mut first[0], &mut second[0]))
115+
}
116+
}
117+
118+
fn demonstrate_pairs_iterator() {
119+
println!("\n=== Bonus: Iterator returning pairs ===");
120+
let mut numbers = vec![0, 1, 2, 3, 4, 5];
121+
122+
let iter = PairsMutIterator::new(&mut numbers[..]);
123+
124+
// Swap each pair
125+
for (a, b) in iter {
126+
std::mem::swap(a, b);
127+
}
128+
129+
println!("After swapping pairs: {:?}", numbers);
130+
assert_eq!(numbers, vec![1, 0, 3, 2, 5, 4]);
131+
}
132+
133+
fn f(a: &mut Box<i32>) -> () {
134+
}
7135

8136
fn main() {
137+
138+
struct Person {
139+
name: String,
140+
id: i32,
141+
}
142+
143+
let b = Person {
144+
name: "John".to_string(),
145+
id: 0,
146+
};
147+
println!("{:?}", b);
148+
149+
//let mut a = vec![0];
150+
//let p = &a[0]; // p is a projection
151+
//a.push(1); // error: cannot borrow `a` as mutable because it is also borrowed as immutable
152+
//println!("p = {:?}", p);
153+
// Demonstrate safe iterators with mutable references
154+
demonstrate_mut_iterator();
155+
demonstrate_pairs_iterator();
156+
157+
// slide 39 - Return by Reference
158+
println!("\n=== Other examples ===");
159+
let mut a = vec![0, 1, 2, 3];
160+
*a.last_mut().unwrap() = 42;
161+
162+
println!("{:?}", a);
163+
// ---
164+
9165
println!("{}", f(42));
166+
167+
// slide 40 - Return by Reference
168+
let mut p = Point { x: 1, y: 2 };
169+
let (x, y) = split_coords(&mut p);
170+
*x = 3;
171+
*y = 4;
172+
println!("p = {:?}", p);
10173
}

0 commit comments

Comments
 (0)