Skip to content

Commit f707b9d

Browse files
committed
Update example
1 parent d83afa0 commit f707b9d

File tree

1 file changed

+27
-14
lines changed

1 file changed

+27
-14
lines changed

examples/reflection/function_reflection.rs

Lines changed: 27 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,8 @@
88
99
use bevy::reflect::func::args::ArgInfo;
1010
use bevy::reflect::func::{
11-
ArgList, DynamicFunction, FunctionInfo, IntoFunction, Return, ReturnInfo,
11+
ArgList, DynamicClosure, DynamicFunction, FunctionInfo, IntoClosure, IntoFunction, Return,
12+
ReturnInfo,
1213
};
1314
use bevy::reflect::Reflect;
1415

@@ -37,7 +38,7 @@ fn main() {
3738
// Luckily, Bevy's reflection crate comes with a set of tools for doing just that!
3839
// We do this by first converting our function into the reflection-based `DynamicFunction` type
3940
// using the `IntoFunction` trait.
40-
let mut function: DynamicFunction = dbg!(add.into_function());
41+
let function: DynamicFunction = dbg!(add.into_function());
4142

4243
// This time, you'll notice that `DynamicFunction` doesn't take any information about the function's arguments or return value.
4344
// This is because `DynamicFunction` checks the types of the arguments and return value at runtime.
@@ -55,22 +56,34 @@ fn main() {
5556
let value: Box<dyn Reflect> = return_value.unwrap_owned();
5657
assert_eq!(value.take::<i32>().unwrap(), 4);
5758

58-
// The same can also be done for closures.
59+
// The same can also be done for closures that capture references to their environment
60+
// using the `IntoClosure` trait.
5961
let mut count = 0;
60-
let increment = |amount: i32| {
61-
count += amount;
62-
};
63-
let increment_function: DynamicFunction = dbg!(increment.into_function());
62+
let increment = |amount: i32| count += amount;
63+
64+
let closure: DynamicClosure = dbg!(increment.into_closure());
6465
let args = dbg!(ArgList::new().push_owned(5_i32));
65-
// `DynamicFunction`s containing closures that capture their environment like this one
66+
// `DynamicClosure`s that mutably capture their environment like this one
6667
// may need to be dropped before those captured variables may be used again.
67-
// This can be done manually with `drop` or by using the `Function::call_once` method.
68-
dbg!(increment_function.call_once(args).unwrap());
68+
// This can be done manually with `drop(closure)` or by using the `DynamicClosure::call_once` method.
69+
dbg!(closure.call_once(args).unwrap());
6970
assert_eq!(count, 5);
7071

72+
// Note that `DynamicFunction` just requires a `'static` lifetime.
73+
// This means that closures that capture variables by taking ownership of them
74+
// can still be converted to a `DynamicFunction`.
75+
let minimum = 5;
76+
let clamp = move |value: i32| value.max(minimum);
77+
78+
let function: DynamicFunction = dbg!(clamp.into_function());
79+
let args = dbg!(ArgList::new().push_owned(2_i32));
80+
let return_value = dbg!(function.call(args).unwrap());
81+
let value: Box<dyn Reflect> = return_value.unwrap_owned();
82+
assert_eq!(value.take::<i32>().unwrap(), 5);
83+
7184
// As stated before, this works for many kinds of simple functions.
7285
// Functions with non-reflectable arguments or return values may not be able to be converted.
73-
// Generic functions are also not supported.
86+
// Generic functions are also not supported (unless manually monomorphized like `foo::<i32>.into_function()`).
7487
// Additionally, the lifetime of the return value is tied to the lifetime of the first argument.
7588
// However, this means that many methods (i.e. functions with a `self` parameter) are also supported:
7689
#[derive(Reflect, Default)]
@@ -92,12 +105,12 @@ fn main() {
92105

93106
let mut data = Data::default();
94107

95-
let mut set_value = dbg!(Data::set_value.into_function());
108+
let set_value = dbg!(Data::set_value.into_function());
96109
let args = dbg!(ArgList::new().push_mut(&mut data)).push_owned(String::from("Hello, world!"));
97110
dbg!(set_value.call(args).unwrap());
98111
assert_eq!(data.value, "Hello, world!");
99112

100-
let mut get_value = dbg!(Data::get_value.into_function());
113+
let get_value = dbg!(Data::get_value.into_function());
101114
let args = dbg!(ArgList::new().push_ref(&data));
102115
let return_value = dbg!(get_value.call(args).unwrap());
103116
let value: &dyn Reflect = return_value.unwrap_ref();
@@ -115,7 +128,7 @@ fn main() {
115128
container.as_ref().unwrap()
116129
}
117130

118-
let mut get_or_insert_function = dbg!(DynamicFunction::new(
131+
let get_or_insert_function = dbg!(DynamicFunction::new(
119132
|mut args, info| {
120133
let container_info = &info.args()[1];
121134
let value_info = &info.args()[0];

0 commit comments

Comments
 (0)