We're kind of getting definitions mixed up here, the || -> {} is just an anonymous function. A closure is a higher-level construct which uses a function scope to create state. So for example, fn counter() -> impl FnMut() -> i32 { let mut val = 0; let _counter = move || -> i32 { let current = val; val += 1; return current; }; return _counter; } this is a closure. calling counter() creates a function scope that holds a `val` in scope, and then subsequent calls to the returned anonymous function mutates that state, without exposing it directly.
In Rust parlance, all functions are called closures, whether they actually close over anything or not. I'm personally not a big fan of this, either. I guess the reason is that they can be closures, so even if they don't take anything into scope, you could argue they are a kind of trivial closure? Yeah, I don't know. I've gotten used to it now.
Ah, yes, this would be the classical example for a closure. You can realize a .counter withouth making it global and without exposing "val" (which has gone out of scope at the time "counter()" returns. I guess, the Rust developers called everything with the "|| -> {}" syntax a closure, even if no variable to close over is involved.
I'm loving your rust series! One request is if you could run your examples so we can see the output (if applicable), not just the code. I also love your VS Code theme (even your older videos had a great theme), which one is it?
I love how closures are so flexible with their verbosity. You can have ||0 if you just want a zero, or you can have |min: f32, max: f32| -> f32 { // a bunch of code }. It makes them so usable.
11:13 two things with move: so we can’t have two threads operating on the same struct? What if we have more than one struct, in the closure… will they all be moved, or can we explicitly specify ownership for each variable in the closure?
At minute 11:50 you are considering that you might get the output in reversed order. Is that possible? Since you are first using println and then creating the thread, i think that it shouldn't change. I understand that if you first created the spawned thread and then you had a print on the main thread, you might have the output in a random order. Of course in that case you should use the same var because of the error you mentioned earlier. Great content, keep it going!
Hello @TheDevMethod please can you explain why you were testing if one of the lists can be printed before the other in 11:42 isn't it that they are run by their lines order in the code?
8:44 I wonder why the compiler doesn’t do this same thing for inferred types for closures… eg show the line which infers the type, along with the line with the type mismatch.
Im still confused...can you step through a function so we can actually see how it works. You go from one example of shirts, to another example of adding 1 without actually seeing what a closure does. I learn best by stepping through a function. Thanks!!!
Thank for the video! I've already read theiught the book and kinda grasped fn traits but hearing other people explain it always helps me understand it better :D With that said, I still have problems combining these Fn traits with async rust. For example if I want to have an sync fn that can take an async fn as an argument, things get weird haha. Do you have problems with that as well?
We're kind of getting definitions mixed up here, the || -> {} is just an anonymous function. A closure is a higher-level construct which uses a function scope to create state. So for example,
fn counter() -> impl FnMut() -> i32 {
let mut val = 0;
let _counter = move || -> i32 {
let current = val;
val += 1;
return current;
};
return _counter;
}
this is a closure. calling counter() creates a function scope that holds a `val` in scope, and then subsequent calls to the returned anonymous function mutates that state, without exposing it directly.
In Rust parlance, all functions are called closures, whether they actually close over anything or not.
I'm personally not a big fan of this, either. I guess the reason is that they can be closures, so even if they don't take anything into scope, you could argue they are a kind of trivial closure?
Yeah, I don't know. I've gotten used to it now.
Ah, yes, this would be the classical example for a closure. You can realize a .counter withouth making it global and without exposing "val" (which has gone out of scope at the time "counter()" returns. I guess, the Rust developers called everything with the "|| -> {}" syntax a closure, even if no variable to close over is involved.
i am addicted to your lectures, thanks, sir
I'm loving your rust series! One request is if you could run your examples so we can see the output (if applicable), not just the code.
I also love your VS Code theme (even your older videos had a great theme), which one is it?
I love how closures are so flexible with their verbosity. You can have ||0 if you just want a zero, or you can have |min: f32, max: f32| -> f32 { // a bunch of code }. It makes them so usable.
11:13 two things with move: so we can’t have two threads operating on the same struct? What if we have more than one struct, in the closure… will they all be moved, or can we explicitly specify ownership for each variable in the closure?
At minute 11:50 you are considering that you might get the output in reversed order. Is that possible? Since you are first using println and then creating the thread, i think that it shouldn't change. I understand that if you first created the spawned thread and then you had a print on the main thread, you might have the output in a random order. Of course in that case you should use the same var because of the error you mentioned earlier.
Great content, keep it going!
You are correct. We would never get a different order. The example should have been a println after spawning the thread. Thanks for catching this!
Hello @TheDevMethod please can you explain why you were testing if one of the lists can be printed before the other in 11:42 isn't it that they are run by their lines order in the code?
8:44 I wonder why the compiler doesn’t do this same thing for inferred types for closures… eg show the line which infers the type, along with the line with the type mismatch.
When would you opt for a regular function instead of a closure?
Im still confused...can you step through a function so we can actually see how it works. You go from one example of shirts, to another example of adding 1 without actually seeing what a closure does. I learn best by stepping through a function. Thanks!!!
code block inside the braces highlightting, is it a plugin or any specific styling?
I used Synth Wave '84 theme extension by Robb Owen
Great explanation man
is there a mistake at 9 20?
great explanitation! thank you
Nice video. I really dislike how rust handles functions and closure types. I know I'm biased because I am a mostly functional programmer but still...
Love the rust content!!
Thank for the video! I've already read theiught the book and kinda grasped fn traits but hearing other people explain it always helps me understand it better :D
With that said, I still have problems combining these Fn traits with async rust. For example if I want to have an sync fn that can take an async fn as an argument, things get weird haha.
Do you have problems with that as well?
I watched the whole 20 minutes waiting for you to show a closure 😢
yo it is an arrow pointing to the right :D