-
-
Notifications
You must be signed in to change notification settings - Fork 2.6k
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
explicitly return from blocks instead of last statement being expression value #629
Comments
Is it really needed to name every such block? Inventing a new name requires lot of mental effort, and it creates unnecessary entities. The example above:
could be written as:
and there would be no ambiguity. The block is used as expression, so the return would always mean "return the block" (and not the parent function). |
It seems like there are a couple of things here. There is a conflict between the desire to be DRY and the desire to follow the Zen of Zig and be explicit. I like the named returns because it is explicit. If we want to follow the "be explicit" rule, then the implicit return of the last thing in the block seems like it violates that. @thejoshwolfe, it seems like, for consistency, you should either have the colon always be leading in declaration and use or trailing. You know from context whether you are declaring or using a label. @PavelVozenilek, in your example above, I would have a hard time seeing the fact that the In GCC you can use statement-expressions which have a different syntax to denote them from regular blocks. It seems like having blocks have values like this is sort of a half-way point to having local functions. That would also solve this. Or perhaps a similar notation for thunks. |
Return inside an expression block would always mean return the value from that block. One would need to know he is looking at expression block, which is always indicated by prior unfinished assignment. (I cannot think about other use case now.) Expression block can be perceived as unnamed local function w/o parameters, then it fits naturally. If there's need to have exit from parent function inside the initialization code then one would need to give up expression blocks and use "regularly structured" code. I dare to guess this would help the readability. The main advantage is no need to invent name for the block. For small blocks the name is redundant, in large blocks it would be lost among the code anyway. |
Un-named expression block could be transformed to local named function with access to parent locals:
Local functions could be then used to keep error handling code in one place:
|
@PavelVozenilek, your comments about local functions are where I was pointing in my comment. Right now the problem is that you need to look at the entire context around a |
Perhaps the solution (to the need to quickly identify whether what I am looking at is expression block/local function or something else) is slightly different syntax. E.g.
(This new syntax could be optional. The traditional The names, IMHO, would only bring much more confusion. Some people will use Exaggerated example with named parameters:
|
For Pavel: it would be more consistent to have a default label for the current block rather than a different bracketing syntax. E.g.
For Josh: This is technically OK but not good style:
In the documentation, you should use the style at the top of the proposal:
With default block label there is no need for the enclosing "initialization:" block. |
@thejoshwolfe the window for syntax changes is closing, so I'm looking at this and I don't see much of a justification for the change. It'd be nice to see why blocks don't directly return expressions as they do in other languages, as it impacts a lot of other issues (#4294 #4412 #5042 etc.) |
As @c-cube already stated, the second problem @thejoshwolfe listed should not actually be a problem: Given that, I think the pros to reverting this change and accepting #4294 would outweigh the cons: Pros
Cons
What makes omitting |
First proposed here: #346 (comment)
tldr: No longer allow omitting a semicolon after the last statement of a block to indicate a return expression. Allow labeled blocks and block-like expressions. Allow explicitly returning from a labeled block with a result expression.
Status quo
You can currently omit the final semicolon in a block to indicate that the block returns a value:
One problem with this is that there are two ways to return a value from a function:
Another problem is that this rule gets confusing when you have implicit semicolons after certain syntactic constructs:
if
,while
,for
, andcomptime
statements if they end with}
, andswitch
statements and blocks (since they always end with}
). So what happens when one of these implicit semicolon constructs is the last statement in a block?Proposal
Returning values from blocks is done via labeled blocks and labeled
return
. For function bodies, this is as simple as using a normalreturn
statement as it exists today. For any other block, the block must be labeled by prefixing the{
withidentifier:
. Then give the block a value viareturn :identifier value
from inside the block.The name of the identifier is scoped to within the block. And since variable names don't go into scope until after the declaration statement, there would be no conflict with these names "
x
":But there would be conflict here:
It's possible to simply "break" out of a block with
return :label
and no expression:If control flow reaches the end of a block, there is an implicit
return :block
with no expression. No expression is the same as a void expression.Only
{
blocks}
can be labeled for this purpose.for
andwhile
loops can be labeled for #346, andif
andswitch
cannot be labeled.You can't use labeled
return
on labeled loops, and you can't use labeledbreak
or labeledcontinue
on labeled blocks.The text was updated successfully, but these errors were encountered: