-
Notifications
You must be signed in to change notification settings - Fork 4
Expand file tree
/
Copy pathclosures.plk
More file actions
47 lines (40 loc) · 1.04 KB
/
closures.plk
File metadata and controls
47 lines (40 loc) · 1.04 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
// we can abuse pointers, generics, and function
// pointers to create hacky closures
// because env is behind a pointer we can erase the
// concrete type to unit to remove env type parameter
struct Fn<T, O> {
env: *mut unit,
function: fn(*mut unit, T) -> O,
}
fn invoke<T, O>(f: Fn<T, O>, arg: T) -> O {
return f.function(f.env, arg);
}
fn closure<E, T, O>(env: *mut E, function: fn(*mut E, T) -> O) -> Fn<T, O> {
// erase concrete type E to unit,
// compiler can infer these types for us
return Fn(env as _, function as _);
}
fn print_num(num: u8) {
if num >= 10 {
print_num(num / 10);
}
putc('0' + num % 10);
}
fn for_each(mut start: u8, end: u8, f: Fn<u8, unit>) {
while start <= end {
invoke(f, start);
start = start + 1;
}
}
fn print_offset(offset: *mut u8, val: u8) {
print_num(*offset + val);
*offset = *offset * 2;
putc(' ');
}
fn main() -> i32 {
let mut delta = 1;
let f = closure(&mut delta, print_offset);
for_each(3, 8, f);
putc('\n');
return 0;
}