Make @(deferred_*) procedures require a new scope #6991
Replies: 1 comment 16 replies
-
|
in some sense you are overlooking a very nice pattern e.g.: // inside a proc or whatever
{
flamegraph.scope("expensive operation")
logger.scope("scraping the whole web")
}and those two should have while I completely understand your suggestion it seems too narrow to only consider the case for UI and I personally don't mind using an on a second read I see you also suggest having another attribute that marks the scope as required. not against it but still this seems to have some weird implications. consider scope_name: begin_menu() {
}adds completely different semantics to the language (because now scope_name: {
begin_menu() {
}
}or another weird case info: Menu_Panel_Info
handle := begin_menu() {
defer menu_info(handle, &info)
}which makes for a very weird read because we might want handle to only live inside the scope which is presupposed when using an info: Menu_Panel_Info
if handle, open := begin_menu(); open {
defer menu_info(handle, &info)
}reads much more cleanly IMO. |
Beta Was this translation helpful? Give feedback.
Uh oh!
There was an error while loading. Please reload this page.
-
Make @(deferred_*) procedures require a new scope
In the spirit of the 1.0 announcement and the call-to-action for suggestions, I decided to write this.
Something that has really been bugging me about the language for quite a while is the fact that
@(deferred_*)attributes have been put into the language to "make UI code easier to write", but it actually doesn't.Consider the following case:
{ begin_menu("Menu 1") // calls end_menu through @(deferred_*) menu_item("1") menu_item("2") menu_item("3") begin_menu("Menu 2") menu_item("A") menu_item("B") // Both calls end up here, and you render a menu inside another. // end_menu() // end_menu() }There are currently two ways of solving this problem, both are ugly.
Solution 1:
{ { begin_menu("Menu 1"); // Semicolon needed for some reason. menu_item("1"); // ... } // end_menu() { begin_menu("Menu 2"); // ... } // end_menu() }Solution 2:
{ // Have the widget return true (Which is not always possible, or desired) // but could also be confusing for people reading the code. // Should they look at the function to see if it EVER returns false? if begin_menu("Menu 1") { // ... } // end_menu() if begin_menu("Menu 1") { // ... } // end_menu() }Although there are currently ways to solve it, even Ryan Fleury on his blog post "UI, Part 5" recognizes that eating the complexity cost of C macros for the purposes of making this ergonomic is worth it, in this way, which is the proposed solution:
{ // Any proc with a @(deferred_*) attribute is REQUIRED to open // a new scope, not doing so is an ERROR. // Or, provide something to mark the scope declaration as required, // @(deferred_*, deferred_scope_required) begin_menu("Menu 1") { menu_item("1") menu_item("2") menu_item("3") } // end_menu() begin_menu("Menu 2") { menu_item("A") menu_item("B") } }What I don't understand is: Odin prides itself on not having implicit behavior, but the current way
deferred_*works IS implicit! Forcingdeferred_*procedures to open a new scope in no way violates the rules of the language, in fact, it makes it follow them even more.Users that don't use LSP's could get clean errors when they call procedures which they have no idea calls another one implicitly at scope exit, and depending on where they do it, some nasty things could happen. Error'ing out when not defining a clear scope takes the dumb case right out, and people who still want to defer things without having an explicit scope can do the usual idiom of calling
defer destroy_whatever()right after aninit_whatever(), which most people do anyway because they don't want implicit behavior.With that said, I do understand that this has been brough up before, but I'm asking you guys to seriously consider it, since it makes UI code a lot nicer to write. Not only UI code, in fact, anything which implicitly manages stacks internally through guarded function calls.
Beta Was this translation helpful? Give feedback.
All reactions