-
-
Notifications
You must be signed in to change notification settings - Fork 3.6k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
[Merged by Bors] - Added example of creating a system from a closure #4327
Conversation
Title suggestion for you @bytemuck (they show up in our commit history, so it's not just bikeshedding): "Added example of creating a system from a closure" |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Cool! Overall, I think this could use a bit more explanation about what's going on: for a lot of readers, this will be their first introduction to closures at all.
I would also like to see a non-capturing closure demonstrated too, just to show that you don't have to use a Local
.
Awesome! I'll take a look for this tomorrow. I gotta sleep, I have school tomorrow. 👍 |
Co-authored-by: Alice Cecile <alice.i.cecile@gmail.com>
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Much clearer!
@bevyengine/docs-team can I get a second review here? |
examples/ecs/system_closure.rs
Outdated
App::new() | ||
.add_plugin(LogPlugin) | ||
// we can use a non-capturing closure as a system | ||
.add_startup_system(non_capturing_closure) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
why did you use startup systems?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I used a startup system because I wanted it to be called only once.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
as you didn't add a scheduler, the app will only run once anyway 🙂
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Oh, that's good to know!
examples/ecs/system_closure.rs
Outdated
}; | ||
|
||
// create a capturing closure, with a Local value. | ||
let capturing_closure = |value: String| { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
this is confusing as this is not a capturing closure
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think I miss understood what's a capturing closure, I'll reread about them and change that when I come back after school.
examples/ecs/system_closure.rs
Outdated
.add_startup_system(move |mut arg: Local<String>| { | ||
*arg = outside_variable.clone(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
why use local to demonstrate capturing? the point of capturing is to not need a local at all
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You're right. I don't know why I did that, I'll review my entire PR and recommit when I get home. I think I tried to demonstrate Local and capturing at the same time, and it is just confusing at the end.
examples/ecs/system_closure.rs
Outdated
outside_variable | ||
); | ||
// you can use outside_variable, or any other variables inside this closure. | ||
// there states will be saved. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
// there states will be saved. |
a) typo "their", not "there" b) I don't think this line adds much :)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You are probably right about this. I'll remove it tomorrow 🙂.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I agree with alice comment other than that I had no idea this was even possible so that's good to know.
examples/ecs/system_closure.rs
Outdated
// create a closure, with a Local value to be initialized. | ||
let complex_closure = |value: String| { | ||
move |mut arg: Local<String>| { | ||
*arg = value.clone(); | ||
info!("Hello from a complex closure! {:?}", arg); | ||
|
||
// 'arg' will be saved between calls. | ||
// you could also use an outside variable like presented in then inlined closures | ||
} | ||
}; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is probably not working the way you want it to. Having a Local
in a capturing closure is useless. Here you're cloning value
to the local at every system execution, so whatever value would the local have would always be replaced by a fresh clone from value
. arg would indeed be saved between calls, but the value wouldn't actually be available to the next call.
Instead you can directly use value
. The outside closure put it in current scope as mutable, the inner closure capture it and actually modify it as every system execution.
// create a closure, with a Local value to be initialized. | |
let complex_closure = |value: String| { | |
move |mut arg: Local<String>| { | |
*arg = value.clone(); | |
info!("Hello from a complex closure! {:?}", arg); | |
// 'arg' will be saved between calls. | |
// you could also use an outside variable like presented in then inlined closures | |
} | |
}; | |
let complex_closure = |mut value: String| { | |
move || { | |
info!("Hello from a complex closure! {:?}", value); | |
value = format!("{}o", value); | |
} | |
}; |
This could probably use more comments to explain what's happening...
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
With some explanation, It makes sense. I should have tested this more aggressively. oops
Wouldn't it be much more useful if you showed receiving a resource or entity query? |
Without the ability to add systems dynamically, this isn't exactly feasible. None of the world's data exists at the time of system initialization. However, once #279 is solved, we should update this example to include that :) |
bors r+ |
Maybe it would be more useful, but I think we should use simplicity over utility in this context, because usually, users will already have knowledge about how the engine works. It will most like not be the first example they will read. |
it should already work, you can use as a system: |
Ah; I'd interpreted the request as "capture data from a resource, and then generate a new system that stores that data". But your read is much more reasonable. |
Fixes #4262