Understanding Rust Closures
antoine.vandecreme.net
Understanding Rust Closures
1–10 of 37 posts
Re: Understanding Rust Closures
#2Re: Understanding Rust Closures
#3Closures are the bread and butter of functional programming, but Rust made closures a complicated mess.
In fact I can’t remember the last time I had to fight with them.
Re: Understanding Rust Closures
#4It will automatically implement the most general, relaxed version (FnMut I think?) and only restrict itself further to FnOnce and Fn based on what you do inside the closure.
So, it can be tricky to know what's going on, and making a code change can change the contract of the closure and therefore where and how it can be used.
(I invite rust experts to correct me if any of the above is mistaken - I always forget the order of precedence for FnOnce/Fn/FnMut and which implies which)
Re: Understanding Rust Closures
#5Closures are the bread and butter of functional programming, but Rust made closures a complicated mess.
Re: Understanding Rust Closures
#6Closures are the bread and butter of functional programming, but Rust made closures a complicated mess.
If you understand the borrow checker, closures are just not that much on top of things. In fact I can’t remember the last time I had to fight with them.
Re: Understanding Rust Closures
#7if I'm not mistaken (and I very well may be!) my primary confusion with closures comes from the fact that: the trait they implement (FnOnce / Fn / FnMut) depends entirely upon what happens inside the closure. It will automatically implement the most general, relaxed version (FnMut I think?) and only restrict itself further to FnOnce and Fn based on what you do inside the closure. So, it can be tricky to know what's g…
Re: Understanding Rust Closures
#8Closures are the bread and butter of functional programming, but Rust made closures a complicated mess.
Re: Understanding Rust Closures
#9Earlier quoted context omitted.
If you understand the borrow checker, closures are just not that much on top of things. In fact I can’t remember the last time I had to fight with them.
I really wanted just yesterday to create a dyn AsyncFnMut, which apparently still needs async-trait to build the stable. but I was pretty much unable to figure out how to make that work with a lambda. saying this is all trivial once you understand the borrow machinery is really understating it.
The comment above isn't saying that closures are trivial. Once you understand the borrow checker, you understand that it's a miracle that closures in Rust can possibly work at all, given Rust's other dueling goals of being a GC-less language with guaranteed memory safety despite letting closures close over arbitrary references. Rust is in uncharted territory here, drawing the map as it goes.
Re: Understanding Rust Closures
#10if I'm not mistaken (and I very well may be!) my primary confusion with closures comes from the fact that: the trait they implement (FnOnce / Fn / FnMut) depends entirely upon what happens inside the closure. It will automatically implement the most general, relaxed version (FnMut I think?) and only restrict itself further to FnOnce and Fn based on what you do inside the closure. So, it can be tricky to know what's g…
The least restrictive for the function itself is the opposite order: FnOnce (it can do anything to its environment, including possibly consuming things without putting them back into a consistent state), followed by FnMut (it has exclusive access to its environment, and so is allowed to mutate it, but not destroy it), followed by Fn (it has only shared access to its environment and therefore is not allowed to mutate it).
Since these orders are inverses of each other, functions that are easier to write are harder to call and vice versa. That’s why they implement the trait with the minimum amount of power possible, so that they can be called in more places.