Is it anywhere near as easy as doing this in Javascript? Or does it require such things as manual memory management?
Is it anywhere near as easy as doing this in Javascript? Or does it require such things as manual memory management?
(See other files in that repo for more examples.)
It's not quite as low-friction as JS, but it's awfully close.
Here's an example using GTK that does something vaguely useful, I have no idea if it's considered idiomatic, but it works as intended: https://github.com/seaneshbaugh/image_viewer/blob/master/src...
The closures themselves are trivial, it's manipulating the stuff outside the closure that's tricky (for a Rust neophyte like me).
The relevant definitions are
let area = Rc::new(RefCell::new(DrawingArea::new()));
and let scale = Rc::new(Cell::new(1.0));
Rather than just define things as usual they need to be wrapped in a Cell (for value types) or RefCell (for reference types) and then wrapped in an Rc so we can keep track of reference counts at run time. {
let scale = scale.clone();
let area = area.clone();
window.connect_key_release_event(move |_, key_event| {
let mut s = scale.get();
let key = key_event.get_keyval() as i32;
if key == gdk_sys::GDK_KEY_plus {
s += 0.1;
} else {
if key == gdk_sys::GDK_KEY_minus {
s -= 0.1;
}
}
scale.set(s);
area.borrow().queue_draw();
Inhibit(false)
});
}
Inside the new scope (which is very important) scale and area are cloned which increments their count, then inside the close scale.get() is used to get a copy of scale (which is possible since it's a float) and then after doing stuff to it based on the key that is pressed it's set using scale.set(). For area it's a bit trickier, it has to first be borrow()'ed before anything can be done with it.Why are you commenting out code? If you delete it, it will still be in your git history. If you have some reason to leave it in, document why and wrap it with a `if false {}` or `if debug {}` instead. That way autoformatters will not destroy your code and the compiler makes sure your code keeps compiling.
Leaving a line empty between statements helps structuring code. Putting an empty line after each statement makes the code as unstructured as without.
Until then, it's easier to review the commented-out bits than to go back through version history. (And plenty easy to delete it when it's ready to be deleted!)
Maybe it's just me, but I find it an eyesore to have large blobs of commented out code laying around even for a short period (not to mention the odds of me remembering to delete them are close to nil).
Ideally your commit message would indicate this. If you're always consistent in the language you use to describe similar changes, you can just search through your git log to find it.
> How do you easily pick out the relevant parts of that diff once many changes have occurred - months or even years later?
You can use `git show` to just look at that one commit where you deleted the code
Closures are difficult to use for this due to Rust's concept of values having one owner, making it fiddly to share values over multiple closures without e.g. wrapping them in Rc<RefCell<T>>.
But note that most UI toolkits already effectively expose all their objects as reference-counted aliasable-mutable—the same as Rc<RefCell<T>>, but more ergonomic.
I wonder if the right solution for this for these frameworks to allow programmers to easily create their own classes in the native widget class hierarchy (COM, Objective-C Foundation, GObject, QObject, etc.), with some combination of macros and other boilerplate generation. Then the rule would effectively be "instead of using Rc<RefCell<T>>, create a native widget class to hold your data if you need to multiply close over it". Not only would this be more ergonomic than the pure-Rust solution, but it'd also interoperate better with the underlying widget system: for example, on macOS and iOS Objective-C introspection APIs would work with such objects.
Doesn't seem too crazy, as long as you don't want to mutate the variables the function closed over.