Is there any way to create a local function like this Python code?
def h():
final = []
def a():
for i in range(5):
final.append(i)
a()
return final
I tried it, but failed:
fn h() -> Vec<i32> {
let mut ff = vec![];
fn a() {
for i in 0..5 {
ff.push(i)
}
};
a();
ff
}
error[E0434]: can't capture dynamic environment in a fn item; use the || { ... } closure form instead
--> src/main.rs:5:13
|
5 | ff.push(i)
| ^^
Functions in Rust don't capture variables from the surrounding environment, period. A "local" function in Rust is really just a global function that isn't globally visible; it can't do anything more than any other global function.
Instead, Rust has closures which are distinct from functions in that they do capture variables from their environment. That would look like this:
fn h() -> Vec<i32> {
let mut ff = vec![];
let mut a = || {
for i in 0..5{
ff.push(i)
}
};
a();
ff
}
Three things to note with this. Firstly, append
is not what you want, you want push
. You should check the documentation for Vec
to see what's available and what methods do. Secondly, you have to make a
mutable because it's mutating something it captured (see also this answer about Fn
, FnMut
, and FnOnce
). Third, it won't compile:
error[E0505]: cannot move out of `ff` because it is borrowed
--> <anon>:9:9
|
3 | let mut a = || {
| -- borrow of `ff` occurs here
...
9 | ff
| ^^ move out of `ff` occurs here
The problem is that by creating the closure, you had to give it a mutable borrow to ff
. However, that borrow prevents anyone else from moving or otherwise messing with ff
. You need to shorten the length of time this borrow exists:
fn h() -> Vec<i32> {
let mut ff = vec![];
{
let mut a = || {
for i in 0..5{
ff.push(i)
}
};
a();
}
ff
}
This works, but is kinda clunky. It's also unnecessary; the above could more cleanly be rewritten by just passing the borrow to ff
into a local function explicitly:
fn h() -> Vec<i32> {
let mut ff = vec![];
fn a(ff: &mut Vec<i32>) {
for i in 0..5{
ff.push(i)
}
}
a(&mut ff);
ff
}
This last one is the best (if you're able to use it), because it keeps it clean when and why ff
is being borrowed.