Description
Throughout the text, the word closure
is used in many cases, including the demonstration highlighted in issue 43, even when there is no closure. In the example (which mirrors the example in the text), no free variables (variables outside the function itself, variables that are part of the enclosing lexical scope) are being referenced, so no closure is necessary. The correct term here is not “closure,” it is “anonymous function,” sometimes called a “lambda”. It is only a closure if it in some way captures (encloses) values from the surrounding context.
Consider the following demonstration, in which the anonymous function described in Issue 43 is replaced with a named function:
fn stringify(i: &u64) -> String {
format!("{}", i)
}
fn main() {
let x = [1, 2, 3, 4, 5];
// let z = x.iter().map(|&x| format!("{}", x)).collect::<Vec<String>>();
let z = x.iter().map(stringify).collect::<Vec<String>>();
println!("{:?}", z);
}
The functionality is unchanged. Since this function is small, used only once, and not pub
, I would expect the compiler to in-line it. Examining the produced assembly language shows that that is the case; the assembly from both the anonymous and named versions is exactly the same. There is no performance loss at all by naming the function.
Don’t take this as too strong a criticism! I absolutely want to commend you on this work! Something this clear and concise has long been needed, and I think you’ve hit a powerful sweet spot between helping newcomers and giving good reminders to experienced old-timers. I want the work to be better, and this, the typing and naming of functions that can be passed to other functions, higher-order programming, was one of the hardest things for me to understand, and I don’t want anyone else to go through that kind of confusion.