Replies: 21 comments
-
I think allowing immediate execution of local function and labmdas will serve the same purpose. Some previous discussions can be found in #249 and #960 |
Beta Was this translation helpful? Give feedback.
-
This is an interesting proposal. On one hand, block expressions are more flexible than sequence expressions, because you are not restricted to a single exit point. They also look much nicer in a multiline context. On the other hand, they are much harder to comprehend with multiple exit points. I would probably allow them in all contexts, except method/lambda expression bodies and expression statements. |
Beta Was this translation helpful? Give feedback.
-
There is a couple of issues with allowing this in other places: Verbosity: sometime you just want to capture some value in the middle of an expression, if ((var x = expr; M(x.a, x.b)))
// instead of
var x = expr;
if (M(x.a, x.b))
// or
if (expr is var x && M(x.a, x.b)) Rewriting this with a block expression is more verbose than current workarounds, and sometime confusing. if ({ var x = expr; break M(x.a, x.b); }) Ambiguity: There are places that this will cause an extensive look ahead, such as: // array initializers
int[] x =
{ // we don't know if this is a block expression until we reach a statement
// block statements
{ // we don't know if this is a block expression until we reach a `break <expression>` With a limited context, we no longer need to deal with such ambiguities. That being said, I don't think this can be considered as an "alternative" to sequence expressions, but enables scenarios that cannot be expressed in a self-contained way. |
Beta Was this translation helpful? Give feedback.
-
The first |
Beta Was this translation helpful? Give feedback.
-
@qrli both? it has the same effect as |
Beta Was this translation helpful? Give feedback.
-
@alrz I realized that after pondering for a moment. Just wanted to say it is confusing, as |
Beta Was this translation helpful? Give feedback.
-
The break statement means get out of the current switch/loop. Now, when it's followed by an expression, it means get out of the current block expression with this value. I think it perfectly fit to the current control flow. See, you can simulate a switch expression with it: x = {
switch(e) {
case 0: break true;
case 1: break false;
default: break (bool?)null;
}
}; |
Beta Was this translation helpful? Give feedback.
-
Having the destination of break change radically just because it has an express afterwards would be really confusing. I think this needs a different keyword - the existing behaviour of return is much closer, but perhaps not a good choice. |
Beta Was this translation helpful? Give feedback.
-
This would prevent the possibility of labeled break. |
Beta Was this translation helpful? Give feedback.
-
I like the idea of block expressions. It's a useful feature in some other languages. Anonymous methods and local functions don't cover all the scenarios in which block expressions would be useful. It seems essential to pick a different keyword for the result of the block expression, because otherwise some useful scenarios disappear. Perhaps void Foo()
{
while (true)
{
// ... other logic ...
char c = Read() ?? // hypothetical Read that returns nullable char
{
if (someCondition)
{
return; // exits Foo, avoids Bar()
}
if (anotherCondition)
{
break; // exits the while loop, allows Bar()
}
use '#'; // new contextual keyword for resolving a block expression with a result
};
// ... other logic ...
}
Bar();
} As far as suggestions to just use anonymous methods and local functions: If you try to put the contents of that block expression in anything that pushes a new frame, the |
Beta Was this translation helpful? Give feedback.
-
I think the restriction that local functions don't know about where it's being called and thus not being able to break from outer loops or return from outer function, is a good thing. Keeps the code simple. If outer break/return is necessary, maybe it's better to not use a block/local anonymous function. |
Beta Was this translation helpful? Give feedback.
-
Beta Was this translation helpful? Give feedback.
-
I find myself wishing for a switch expression more often than I find myself wishing for block expression. However, in the case of a switch expression, I believe a unique syntax (just as there's a unique syntax for the ternary conditional operator) would add clarity. As an example, using a type of BNF: ::= : | * : Where evaluates to a single value that matches a or selects the default key: *
|
Beta Was this translation helpful? Give feedback.
-
Switch expressions are coming to C# 8.0.
I disagree. The ternary operator is fairly confusing, to the point where it's often not recommended for anything but the most simple expressions. A switch expression will certainly be more complicated thus a more structured syntax would provide more clarity, especially to anyone who has to read that code after it has been written.
It will result in a runtime exception. Anything else, especially a default value, would only be a very subtle vector for bugs. |
Beta Was this translation helpful? Give feedback.
-
Restricting the usage as stated in the first sentence of the proposal feels weird to me. A block expression should be allowed in all places where an expression is expected. my take on it:
beeps.
doesn't. IntelliSense tells me which code block is affected by the return statement as known from keywords like break and continue.
In essence, a block expression can always be translated to a local function declared in a particular scope. We just drop the declaration and invocation syntax. In other words, semantically it's the invocation of an anonymous local function. I think users often like to understand ideas once and then apply them in unforeseen scenarios. If we could state that a block expression isn't much more than the invocation of an anonymous local method then it's not far fetched to assume from a users perspective the following to work as well: Sugaring the sequence expression further might be a different topic. |
Beta Was this translation helpful? Give feedback.
-
A |
Beta Was this translation helpful? Give feedback.
-
it's not confusing as it is easy to explain: it behaves like a local function with its pros and cons. #1167 (comment) |
Beta Was this translation helpful? Give feedback.
-
That is changing its meaning. Currently |
Beta Was this translation helpful? Give feedback.
-
@HaloFour |
Beta Was this translation helpful? Give feedback.
-
Indeed, not all expressions can be statements and not all statements can be expressions. But you're proposing to use an existing statement syntax for use as an expression, and to subtly change the behavior of certain keywords within the block of that expression. With lambdas and local functions you have to use completely new syntax to surround the body. The language team has proposed and championed an alternative syntax for these kinds of expressions: |
Beta Was this translation helpful? Give feedback.
-
@HaloFour note, however, the author of this proposal says:
Having a return statement within a block (several times) feels different than a "declaration expression" that returns the value of the final expression within the block. But for me, this #973 works well. Those expressions, of course, are primarily for allowing brevity of expression. |
Beta Was this translation helpful? Give feedback.
Uh oh!
There was an error while loading. Please reload this page.
-
block expressions
A block expression lets you to use statements in an expression context, but restricted to assignments, initializers and the switch expression for easier disambiguation.
->
To return the result from a block expression we use
break <expression>
syntax. Yetbreak;
andreturn;
statements are permitted and would work the same way they do today. A block expression need abreak <expression>;
to be always reachable - just likereturn
in non-void returning methods.Open question: where else we could permit a usage of block expressions? This is the argument against more expression-based constructs like
lock
andusing
expressions, so that we can use the same statement form in an expression context.PS: I suggested this as an alternative under sequence expressions but I figured they are actually very different features and make sense beside each other. (I suspected this is a dup but couldn't find any)
Beta Was this translation helpful? Give feedback.
All reactions