gtk-rs / gtk-rs-core

Rust bindings for GNOME libraries
https://gtk-rs.org/gtk-rs-core
MIT License
279 stars 111 forks source link

[FEATURE REQUEST] `use_cloned!` macro #768

Open ranfdev opened 1 year ago

ranfdev commented 1 year ago

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:

Implementation details I have a basic working implementation (~50 lines) based on macro_rules. It has the following drawbacks:

What do you think?

sdroege commented 1 year ago

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.

ranfdev commented 1 year ago

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.

jf2048 commented 1 year ago

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

euclio commented 1 year ago

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);
  }
)