-
Notifications
You must be signed in to change notification settings - Fork 208
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
hope for do expression #132
Comments
I don't read JSX very well, but semantically it looks similar to the argument blocks idea. Could you please provide a full Flutter code sample showing how |
A do expression is basically just a way to put a block of statements in a context where an expression is expected: print(do {
var a = 1;
var b = 2;
a + b
}); // Prints "3". It's like an IIFE, except that IIFE's don't compose correctly with Interestingly, we are considering adding a construct like this as part of the intermediate language that Dart is compiled to. See: #127 (comment) It would be handy to have as a meta-syntax for specifying language features that are syntactic sugar. I'm not sure how useful it would be as a user-visible syntax feature. |
This is one usecase in JSX: return (
<nav>
<Home />
{
do {
if (loggedIn) {
<LogoutButton />
} else {
<LoginButton />
}
}
}
</nav>
) Without a do expression, you either have to write:
For Flutter, if you go with the last option, you probably would write something like this: var button;
if (loggedIn) {
button = LogoutButton();
} else {
button = LoginButton();
}
return Nav(
children: [
Home(),
button,
]
); The control flow collection proposal tries to solve this in the following way: return Nav(
children: [
Home(),
if (loggedIn)
LogoutButton()
else
LoginButton(),
]
); If Dart would adopt do expressions, it would look like this: return Nav(
children: [
Home(),
do {
if (loggedIn) {
LogoutButton();
} else {
LoginButton();
}
},
]
); The Flow Collection Proposal is shorter, and also allows to add "Nothing" to the collection, when there is no else. However do expression can also be used in other contexts, for example, if you want type inference, no- nullability and immmutability in the following code: factory Car(Position start, bool horizontal, int length) {
var end;
if (horizontal) {
end = start + new Position(length - 1, 0);
} else {
end = start + new Position(0, length - 1);
}
var positions;
if (length == 2) {
positions = <Position>[start, end];
} else {
if (horizontal) {
positions = <Position>[start, start + new Position(1, 0), end];
} else {
positions = <Position>[start, start + new Position(0, 1), end];
}
}
return new Car._(start, end, horizontal, length, positions);
} With do expression it can be written like: factory Car(Position start, bool horizontal, int length) {
final end = do {
if (horizontal) {
start + new Position(length - 1, 0);
} else {
start + new Position(0, length - 1);
}
}
final positions = do {
if (length == 2) {
<Position>[start, end];
} else {
if (horizontal) {
<Position>[start, start + new Position(1, 0), end];
} else {
<Position>[start, start + new Position(0, 1), end];
}
}
}
return new Car._(start, end, horizontal, length, positions);
} |
There are complications to allowing statements with expressions. Currently, the only control flow an expression can do is throwing (which is also the only non-local control flow). If we allow expression-blocks like |
@lrhn This question is also discussed here: |
return Nav(
children: [
Home(),
do {
if (loggedIn) {
LogoutButton();
} else {
LoginButton();
}
},
]
); For that to work, there would have to be some implicit magic that the value usually discarded by a statement expression would somehow propagate out to the surrounding context. How would the language know that you want to keep the values returned by return Nav(
children: [
Home(),
do {
print("Just some debug code.")
if (loggedIn) {
LogoutButton();
} else {
LoginButton();
}
},
]
); Also, what happens if the do expression tries to emit multiple values, but is used in a context where only one is expected? What would this do: var wat = do {
LogoutButton();
LoginButton();
}; |
I don't know if flutter support concept of return Nav(
children: [
Home(),
do {
// Auth is a RenderPropsWidget that its child should be a callback function, and pass a boolean login status to that function
var loggedIn = yield Auth();
if (loggedIn) {
LogoutButton();
} else {
LoginButton();
}
},
]
); And we can leave out the keyword
|
I couldn’t find really good documentation, but I believe it works similar as in “expression orientated languages”, the last executed statement expression is value that the You can try out how it works here. It is included in the babel stage-1 preset. |
Interestingly, in Kotlin you can do val end = if (horizontal) {
start + new Position(length - 1, 0);
} else {
start + new Position(0, length - 1);
} or its more preferred variant val end = when {
horizontal -> start + new Position(length - 1, 0);
else -> start + new Position(0, length - 1);
} |
Just to toss in my 2 cents, I think a feature like this would be particularly useful now that switch expressions exist and |
Just adding to the "hey I'd like this" end of the conversation! As @mattrberry says above, this is especially useful for the new switch expressions-right now it's a bit ungainly that you might have to refactor your expression to a statement if you need a multi-statement body in your switch. I go into a lot more depth here: FWIW, as others have already pointed out, you can already do this today with IIFEs (Immediately Invoked Function Expressions).
Future<String> funcA(int n) async {
return switch (n) {
0 => () async {
await someAsyncSideEffect();
return 'zero';
}(),
_ => Future.value(n.toString()),
};
} And if you really want All this said, I definitely wouldn't complain if a language native I don't think I love the idea of a var myString = do {
if (false) {
'foo';
} else {
'bar';
}
} but this is a compile error: var myString = if (false) {
'foo';
} else {
'bar';
] this is semantically coherent, but pretty counterintuitive and hard to grock imo. |
I think
do expression
is very useful in flutter's html-like code.And
do expression
shouldn't be just anonymous function calling even though their code length are very near, because using anonymous function calling, the generator status can not pass down.please have a look at tc39/proposal-do-expressions#37
The text was updated successfully, but these errors were encountered: