-
Notifications
You must be signed in to change notification settings - Fork 566
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
Design idea regarding Event::Command #1142
Comments
Personally, I don't think it is worth the additional effort. Having a convention to just prefix all selectors with the crate name is just much simpler and does the trick. For example all commands offered by druid are called something like Of course, if Rust should ever offer some ergonomic way to get access to constant, unique ids, we will switch to that for safety and ergonomics. Until then, we will probably have to live with string identifiers. Thanks for writing down your ideas though! |
Hmm, I would have thought something like the following might have worked, Edit: It does actually work if we declare them static instead of const... |
I've actually tried this approach during my search for an alternative for string id's and could not stop the compiler to optimize all selectors to a single pointer :/
Another issue is that both |
Also i'm not particularly aware of the semantics defining Perhaps we can do something with I don't think its reasonable to expect though that rustc could ever optimize it away, since it pretty well hides the underlying allocation from the compiler. We could seek clarification I suppose if we decide this is an option worth pursuing. |
When I initially came up with this idea I was thinking about the perf implications as well as the ergonomics, but you've mentioned that Selectors are actually just doing a pointer comparison and not a full string comparison, so that helps. I'm not sure what the cost of the any downcast is compared to an enum destructure, but probably not much. However this raises an interesting issue to me. This style of pointer comparison only works if everything is statically compiled together. Now while that is the default in rust, compiling to a dylib is supported. If one were to define the same string in two different places, compile them to separate binaries/libraries, and have one load the other dynamically, these Selectors wouldn't match, despite the string contents being identical. This is an extremely unusual use case though, so I don't think it really matters. And to solve it you could just expose one of the strings publicly instead of defining it twice. For an additional perspective on the enum based approach, take a look at the library Iced. The way they implement it is different from how it would have to be in Druid however. They have an Application trait that the root of your app implements, which has an associated type Message. That Message type then gets applied to all of your widgets inside the Application. Druid has no root-level construct like this. |
Honestly, if we manage to reach a point where comparison of command selectors becomes relevant, we will have already succeeded in building the fastest UI library in existence :) Ergonomics is really the only reason I would be convinced to change this.
That's not quite right, Druid does a string comparison (which gets optimized with pointer comparison by Rust).
Yeah, I don't think this approach would work for Druid. It could probably be done with something like parameterised modules but I doubt that will ever become a feature of Rust.
That's my biggest issue with this approach. Another problem is debugging. Right now it is quite nice because every command has a unique, human-readable id that can easily be |
@smmalis37 Noob suggestion, but the delegate you register with the launcher strikes me as a pretty straightforward place to attach a potential Message type to. Or even making AppLauncher a trait for users to implement, and have it all on there? I don't know how all the *Ctx are implementen/constructed regarding commands, but given that there is some amount of plugging and plumbing at the top level anyway, why not encode it more coherently and also enable deeper control over command/message objects? |
I'd be curious to see a sketch of this, but my current feeling is that adding a top-level user-defined type is going to end up infecting most of the other type signatures in a pretty big way, and it isn't totally clear to me what the benefits are. One possible exception to this would be to have there be a separate 'Event::AppMessage' event, that would be a single place where you can inject a type, and this would hopefully only change the signatures of the |
I'm going to close this. For now all druid commands have a name starting with |
also there is |
The fact that it's possible for a user-defined command to accidentally collide with one of Druid's predefined commands doesn't feel great to me (as incredibly unlikely as it is). Therefore my first suggestion is for the Command variant to be split into two new Event varaints: DruidCommand and UserCommand (names subject to bikeshedding). DruidCommand can then become an enum with all the currently constant Selectors becoming variants instead.
My next thought was that it would feel more ergonomic to me if this new UserCommand type could become a user-defined enum, instead of using Any. It would likely require some additional threading of a new generic parameter, so this may not be worth it. But if it was done it could eliminate the Selector type entirely. We've got a type system, we should use it instead of just stringly typing things imo.
Both of these would be rather large breaking changes, so they may not be worth it. Thoughts?
The text was updated successfully, but these errors were encountered: