gtk-rs-core
gtk-rs-core copied to clipboard
[FEATURE REQUEST] `use_cloned!` macro
I propose adding a use_cloned! macro with the following semantics:
button.connect_clicked(use_cloned![move |_btn| {
weak!(label, panic).set_label("clicked the button");
strong!(label2).set_label("I'm strong");
}]);
Benefits:
- Formatting from rustfmt
I found out that by using the same macro format as
vec![expr1, expr2, ...]rustfmt can format the macro as avec![]. The content of this macro is always a valid rust expression, so everything works out. - Easier to use
The cloning happens automatically, no need to specify what you need beforehand. Just wrap the variable you want to use with
strong!orweak!.
Implementation details
I have a basic working implementation (~50 lines) based on macro_rules. It has the following drawbacks:
- Each variable can only be cloned one time in the same
use_cloned!block. This can be solved by writing the implementation using proc macros - You can't nest the
strong!andweak!macros inside another macro. Eg: You can't doprintln!("{:?}", cloned!(a)). This can be solved if needed.
What do you think?
Formatting from rustfmt
That would be good to have but it's a bit ugly to use vec syntax here. We could get the same behaviour with an attribute macro though.
- This can be solved by writing the implementation using proc macros
I think you lose the rustfmt support with the vec-style macro again then.
- The cloning happens automatically, no need to specify what you need beforehand.
IMHO that's an anti-feature :) Having to specify exactly what you need upfront makes it clear when reading the code what exactly happens there.
About the formatting:
With more testing, I found out that rustfmt seems to not care about the definition of the macro; it only cares about how the macro gets used. As long as the macro call contains an expression, the expression will get formatted. And the formatting works with both round brackets, (), and square brackets. Not {}.
Having to specify exactly what you need upfront makes it clear when reading the code what exactly happens there.
I think who wants complete control over the cloning behavior is going to clone everything manually anyway. Cloning is inevitable, so why not make it painless?
Anyway, I will probably just make a separate crate for this.
See the clone_block macro I made for an example of how to do it using an attribute: https://github.com/jf2048/gobject#clone_block-macro
The idea is to get it a bit closer to how captures are specified in C++ and Swift
I've been thinking about trying a more rustfmt-friendly syntax with attributes, too:
clone!(
#[weak]
foo,
#[strong(name = baz)]
self.bar,
move |_, _| {
println!("{}", baz);
}
)