Finding Closure in Rust
huonw.github.io
huonw.github.io
Rust ties closures closely to lambdas, but that's not inherently necessary. The article says "Syntactically, a closure in Rust is an anonymous function value defined a little like Ruby, with pipes: |arguments...| body." Actually, that's a lambda, not a closure.
A lambda which references no variables from an outer scope is not a closure.
|x| x*x
is a Rust lambda that isn't a closure.On the other hand, a nested function in Python which references variables from the outer function is a closure that isn't a lambda. That's also true in Javascript. In Rust, you can nest functions, but you can't generate a closure that way. A reference to the outer function scope in a Rust nested function generates an error message. I was surprised by that; I tried to write a closure in Rust as a nested function, and there's an specific error message for that.
The most valuable special case IMO for captureless closure would be allowing them to coerce to (extern) fn types, useful for writing e.g. C callbacks directly inline.
fn some_function<F>(some_closure: F)
On the other hand, you can write a nested function and pass it as a parameter to a non-generic function. It just can't make references that would make it a closure. That's because Rust closures are really a syntactic hack for traits.(All this complexity may turn off C programmers, and their management, for things that really need to be in something safer than C. The people who participate in language discussions do understand this stuff, but they're not the ones writing embedded code. Rust could go the way of C++, where metaprogramming became The Beast that Ate the Language.)
fn foo(x: &Fn(i32)) {
x(5);
}
fn main() {
foo(&|x| println!("x: {}", x));
}
Or you can use std::boxed::FnBox in order to take a Box<FnBox(i32)> but that's currently marked as unstable (it exists because you can't take Box<FnOnce(..)> as you can't move out of the box in order to call the lambda as it does not have a statically-known size, but if you're ok taking Fn or FnMut then you don't need it). fn foo<T: FnOnce(i32)>(x: T) {
x(5);
}
fn bar(_: i32) {
println!("Bar");
}
fn main() {
foo(bar);
}