Discussion:
[dart-misc] another thought on if(){ ...} else {...} constructs in strong mode and type inference
Kasper Peulen
2015-12-14 21:11:46 UTC
Permalink
The last couple of weeks, I've been exploring strong mode.
And I try to not left type local variables, but use inference instead.

One type of construct that feels a bit off in this scenario, is
initializing a local variable to null, and do an if ... else ... construct
to calculate the value.
Same for try ... catch kind of constructs.

In this way, there is no type inference possible.

My question is, how do you guys do this? And what would be a good style?

I have here maybe a good example, I'm coding right now. Please don't put
too much attention about the actual code, I just want to give an example,
for a general concept:

class Car {
final Position start;
final Position end;
final bool horizontal;
final int length;
final List<Position> positions;

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);
}

Car._(this.start, this.end, this.horizontal, this.length, this.positions);
}


So there is no type inference possible here. And strong mode gets worried.

So there are a couple of possibilities to get type inference to work,
probably the shortest one (and maybe the least readable):

factory Car(Position start, bool horizontal, int length) {
var end = horizontal
? start + new Position(length - 1, 0)
: start + new Position(0, length - 1);

var positions = length == 2
? <Position>[start, end]
: horizontal
? <Position>[start, start + new Position(1, 0), end]
: <Position>[start, start + new Position(0, 1), end];
return new Car._(start, end, horizontal, length, positions);
}


Another option is using, two extra static functions:

static Position _getEnd(Position start, bool horizontal, int length) {
if (horizontal) {
return start + new Position(length - 1, 0);
} else {
return start + new Position(0, length - 1);
}
}

static List<Position> _getPositions(
Position start, bool horizontal, int length, Position end) {
if (length == 2) {
return <Position>[start, end];

} else {
if (horizontal)
return <Position>[start, start + new Position(1, 0), end];

else
return <Position>[start, start + new Position(0, 1), end];

}
}

factory Car(Position start, bool horizontal, int length) {

var end = _getEnd(start, horizontal, length);
var positions = _getPositions(start, horizontal, length, end);
return new Car._(start, end, horizontal, length, positions);
}


Generally, I would not go for this, it is quite much extra chars to type
(annotating all the types of those two functions).
And for two functions that I only use one time, only in the factory
constructor.

There is yet another alternative, which may look a bit ugly, but does a
good job in some sense imo:

factory Car(Position start, bool horizontal, int length) {
var end = () {
if (horizontal) {
return start + new Position(length - 1, 0);
} else {
return start + new Position(0, length - 1);
}
}();
var positions = () {
if (length == 2) {
return <Position>[start, end];

} else {
if (horizontal)
return <Position>[start, start + new Position(1, 0), end];

else
return <Position>[start, start + new Position(0, 1), end];

}
}();
return new Car._(start, end, horizontal, length, positions);
}


So, now what style do you guys think fits the job best here, to get
inference working?

I think the problem is, that there is no clear winner. It is also quite
hard to think about some language addition that could give a clear winner
here.

Here is some thought I had today. Basically, allowing the get keyword in
local scope, as some sugar for anonymous functions that immediately execute.

factory Car(Position start, bool horizontal, int length) {
var end = get {

if (horizontal) {
return start + new Position(length - 1, 0);
} else {
return start + new Position(0, length - 1);
}
}
var positions = get {
if (length == 2) {
return [start, end];
} else {
if (horizontal)
return [start, start + new Position(1, 0), end];
else
return [start, start + new Position(0, 1), end];
}
}
return new Car._(start, end, horizontal, length, positions);
}


Any thoughts? Other ideas? And maybe more practically, how would you write
this kind of code using Dart today?
--
For other discussions, see https://groups.google.com/a/dartlang.org/

For HOWTO questions, visit http://stackoverflow.com/tags/dart

To file a bug report or feature request, go to http://www.dartbug.com/new
---
You received this message because you are subscribed to the Google Groups "Dart Misc" group.
To unsubscribe from this group and stop receiving emails from it, send an email to misc+***@dartlang.org.
'Andreas Kirsch' via Dart Misc
2015-12-14 21:18:19 UTC
Permalink
Imo, we should do a type inference here that works with type intersections.
Ie when we look at the code we should infer the highest common type
denominator and use that for the variable.

Ie if you have
```
var a;
if (...) {
a = 1.0;
} else {
a = 'hello';
}
```
a should be of inferred type Object.

Using type unions or accepting dynamic actually makes automated
refactorings really difficult and creates hidden coupling between different
types.

What do you think?

Thanks,
Andreas
Post by Kasper Peulen
The last couple of weeks, I've been exploring strong mode.
And I try to not left type local variables, but use inference instead.
One type of construct that feels a bit off in this scenario, is
initializing a local variable to null, and do an if ... else ... construct
to calculate the value.
Same for try ... catch kind of constructs.
In this way, there is no type inference possible.
My question is, how do you guys do this? And what would be a good style?
I have here maybe a good example, I'm coding right now. Please don't put
too much attention about the actual code, I just want to give an example,
class Car {
final Position start;
final Position end;
final bool horizontal;
final int length;
final List<Position> positions;
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);
}
Car._(this.start, this.end, this.horizontal, this.length, this.positions);
}
So there is no type inference possible here. And strong mode gets worried.
So there are a couple of possibilities to get type inference to work,
factory Car(Position start, bool horizontal, int length) {
var end = horizontal
? start + new Position(length - 1, 0)
: start + new Position(0, length - 1);
var positions = length == 2
? <Position>[start, end]
: horizontal
? <Position>[start, start + new Position(1, 0), end]
: <Position>[start, start + new Position(0, 1), end];
return new Car._(start, end, horizontal, length, positions);
}
static Position _getEnd(Position start, bool horizontal, int length) {
if (horizontal) {
return start + new Position(length - 1, 0);
} else {
return start + new Position(0, length - 1);
}
}
static List<Position> _getPositions(
Position start, bool horizontal, int length, Position end) {
if (length == 2) {
return <Position>[start, end];
} else {
if (horizontal)
return <Position>[start, start + new Position(1, 0), end];
else
return <Position>[start, start + new Position(0, 1), end];
}
}
factory Car(Position start, bool horizontal, int length) {
var end = _getEnd(start, horizontal, length);
var positions = _getPositions(start, horizontal, length, end);
return new Car._(start, end, horizontal, length, positions);
}
Generally, I would not go for this, it is quite much extra chars to type
(annotating all the types of those two functions).
And for two functions that I only use one time, only in the factory
constructor.
There is yet another alternative, which may look a bit ugly, but does a
factory Car(Position start, bool horizontal, int length) {
var end = () {
if (horizontal) {
return start + new Position(length - 1, 0);
} else {
return start + new Position(0, length - 1);
}
}();
var positions = () {
if (length == 2) {
return <Position>[start, end];
} else {
if (horizontal)
return <Position>[start, start + new Position(1, 0), end];
else
return <Position>[start, start + new Position(0, 1), end];
}
}();
return new Car._(start, end, horizontal, length, positions);
}
So, now what style do you guys think fits the job best here, to get
inference working?
I think the problem is, that there is no clear winner. It is also quite
hard to think about some language addition that could give a clear winner
here.
Here is some thought I had today. Basically, allowing the get keyword in
local scope, as some sugar for anonymous functions that immediately execute.
factory Car(Position start, bool horizontal, int length) {
var end = get {
if (horizontal) {
return start + new Position(length - 1, 0);
} else {
return start + new Position(0, length - 1);
}
}
var positions = get {
if (length == 2) {
return [start, end];
} else {
if (horizontal)
return [start, start + new Position(1, 0), end];
else
return [start, start + new Position(0, 1), end];
}
}
return new Car._(start, end, horizontal, length, positions);
}
Any thoughts? Other ideas? And maybe more practically, how would you write
this kind of code using Dart today?
--
For other discussions, see https://groups.google.com/a/dartlang.org/
For HOWTO questions, visit http://stackoverflow.com/tags/dart
To file a bug report or feature request, go to http://www.dartbug.com/new
---
You received this message because you are subscribed to the Google Groups
"Dart Misc" group.
To unsubscribe from this group and stop receiving emails from it, send an
--
Why is this e-mail so short? Answer: five.sentenc.es.
--
For other discussions, see https://groups.google.com/a/dartlang.org/

For HOWTO questions, visit http://stackoverflow.com/tags/dart

To file a bug report or feature request, go to http://www.dartbug.com/new
---
You received this message because you are subscribed to the Google Groups "Dart Misc" group.
To unsubscribe from this group and stop receiving emails from it, send an email to misc+***@dartlang.org.
Kasper Peulen
2015-12-14 22:04:52 UTC
Permalink
I think that in strong mode, if you initialize the variable as null, and
you don't add type annotations, the inferred type will always be dynamic.

If I understand it correctly, the inferred type must be determined when the
the variable is initialized. Because otherwise, you are basically, changing
type after creation, and that is exactly what a dynamic variable does.

The analyzer also keeps track of the "propagated" type, I believe, for code
completion etc, but I believe that this is different concept.
So for example.

var arg;
var arg = <int>[1];

will have propogated type List<int> (you will get code completion for a),
but inferred type is dynamic, and a function that only accepts List<int> as
argument, will not accept `arg` (in strong mode), without a runtime type
check.
Post by 'Andreas Kirsch' via Dart Misc
Imo, we should do a type inference here that works with type
intersections. Ie when we look at the code we should infer the highest
common type denominator and use that for the variable.
Ie if you have
```
var a;
if (...) {
a = 1.0;
} else {
a = 'hello';
}
```
a should be of inferred type Object.
Using type unions or accepting dynamic actually makes automated
refactorings really difficult and creates hidden coupling between different
types.
What do you think?
Thanks,
Andreas
Post by Kasper Peulen
The last couple of weeks, I've been exploring strong mode.
And I try to not left type local variables, but use inference instead.
One type of construct that feels a bit off in this scenario, is
initializing a local variable to null, and do an if ... else ... construct
to calculate the value.
Same for try ... catch kind of constructs.
In this way, there is no type inference possible.
My question is, how do you guys do this? And what would be a good style?
I have here maybe a good example, I'm coding right now. Please don't put
too much attention about the actual code, I just want to give an example,
class Car {
final Position start;
final Position end;
final bool horizontal;
final int length;
final List<Position> positions;
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);
}
Car._(this.start, this.end, this.horizontal, this.length, this.positions);
}
So there is no type inference possible here. And strong mode gets worried.
So there are a couple of possibilities to get type inference to work,
factory Car(Position start, bool horizontal, int length) {
var end = horizontal
? start + new Position(length - 1, 0)
: start + new Position(0, length - 1);
var positions = length == 2
? <Position>[start, end]
: horizontal
? <Position>[start, start + new Position(1, 0), end]
: <Position>[start, start + new Position(0, 1), end];
return new Car._(start, end, horizontal, length, positions);
}
static Position _getEnd(Position start, bool horizontal, int length) {
if (horizontal) {
return start + new Position(length - 1, 0);
} else {
return start + new Position(0, length - 1);
}
}
static List<Position> _getPositions(
Position start, bool horizontal, int length, Position end) {
if (length == 2) {
return <Position>[start, end];
} else {
if (horizontal)
return <Position>[start, start + new Position(1, 0), end];
else
return <Position>[start, start + new Position(0, 1), end];
}
}
factory Car(Position start, bool horizontal, int length) {
var end = _getEnd(start, horizontal, length);
var positions = _getPositions(start, horizontal, length, end);
return new Car._(start, end, horizontal, length, positions);
}
Generally, I would not go for this, it is quite much extra chars to type
(annotating all the types of those two functions).
And for two functions that I only use one time, only in the factory
constructor.
There is yet another alternative, which may look a bit ugly, but does a
factory Car(Position start, bool horizontal, int length) {
var end = () {
if (horizontal) {
return start + new Position(length - 1, 0);
} else {
return start + new Position(0, length - 1);
}
}();
var positions = () {
if (length == 2) {
return <Position>[start, end];
} else {
if (horizontal)
return <Position>[start, start + new Position(1, 0), end];
else
return <Position>[start, start + new Position(0, 1), end];
}
}();
return new Car._(start, end, horizontal, length, positions);
}
So, now what style do you guys think fits the job best here, to get
inference working?
I think the problem is, that there is no clear winner. It is also quite
hard to think about some language addition that could give a clear winner
here.
Here is some thought I had today. Basically, allowing the get keyword in
local scope, as some sugar for anonymous functions that immediately execute.
factory Car(Position start, bool horizontal, int length) {
var end = get {
if (horizontal) {
return start + new Position(length - 1, 0);
} else {
return start + new Position(0, length - 1);
}
}
var positions = get {
if (length == 2) {
return [start, end];
} else {
if (horizontal)
return [start, start + new Position(1, 0), end];
else
return [start, start + new Position(0, 1), end];
}
}
return new Car._(start, end, horizontal, length, positions);
}
Any thoughts? Other ideas? And maybe more practically, how would you
write this kind of code using Dart today?
--
For other discussions, see https://groups.google.com/a/dartlang.org/
For HOWTO questions, visit http://stackoverflow.com/tags/dart
To file a bug report or feature request, go to http://www.dartbug.com/new
---
You received this message because you are subscribed to the Google Groups
"Dart Misc" group.
To unsubscribe from this group and stop receiving emails from it, send an
--
Why is this e-mail so short? Answer: five.sentenc.es.
--
For other discussions, see https://groups.google.com/a/dartlang.org/

For HOWTO questions, visit http://stackoverflow.com/tags/dart

To file a bug report or feature request, go to http://www.dartbug.com/new
---
You received this message because you are subscribed to the Google Groups "Dart Misc" group.
To unsubscribe from this group and stop receiving emails from it, send an email to misc+***@dartlang.org.
'Leaf Petersen' via Dart Misc
2015-12-14 22:36:35 UTC
Permalink
We've discussed this issue internally a number of times, and probably will
again. In general we've so far tried to keep our inference fairly simple,
both to avoid programmer surprise, and to avoid committing to
algorithmically more expensive inference. In the general case, Andreas'
suggestion leads to computing a fixed point, since variables may be defined
in terms of other variables (there are of course intermediate points short
of doing the full fixed-point iteration, and points beyond it as well).
This isn't by any means meant to imply that these things can't or shouldn't
be done - just that we've tried to start out fairly conservatively on all
axes with a mind to generalizing where we need to.

My personal take is that for the time being the nicest pattern here is just
to have a convention of left annotating variables that are initialized
conditionally. Note that strong mode will partially make up for the added
verbosity by inferring for you the `<Position>` on the list literals. I
realize that this is a bit of a departure from the preferred style though.

cheers,
-leaf
Post by Kasper Peulen
I think that in strong mode, if you initialize the variable as null, and
you don't add type annotations, the inferred type will always be dynamic.
If I understand it correctly, the inferred type must be determined when
the the variable is initialized. Because otherwise, you are basically,
changing type after creation, and that is exactly what a dynamic variable
does.
The analyzer also keeps track of the "propagated" type, I believe, for
code completion etc, but I believe that this is different concept.
So for example.
var arg;
var arg = <int>[1];
will have propogated type List<int> (you will get code completion for a),
but inferred type is dynamic, and a function that only accepts List<int> as
argument, will not accept `arg` (in strong mode), without a runtime type
check.
Post by 'Andreas Kirsch' via Dart Misc
Imo, we should do a type inference here that works with type
intersections. Ie when we look at the code we should infer the highest
common type denominator and use that for the variable.
Ie if you have
```
var a;
if (...) {
a = 1.0;
} else {
a = 'hello';
}
```
a should be of inferred type Object.
Using type unions or accepting dynamic actually makes automated
refactorings really difficult and creates hidden coupling between different
types.
What do you think?
Thanks,
Andreas
Post by Kasper Peulen
The last couple of weeks, I've been exploring strong mode.
And I try to not left type local variables, but use inference instead.
One type of construct that feels a bit off in this scenario, is
initializing a local variable to null, and do an if ... else ... construct
to calculate the value.
Same for try ... catch kind of constructs.
In this way, there is no type inference possible.
My question is, how do you guys do this? And what would be a good style?
I have here maybe a good example, I'm coding right now. Please don't put
too much attention about the actual code, I just want to give an example,
class Car {
final Position start;
final Position end;
final bool horizontal;
final int length;
final List<Position> positions;
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);
}
Car._(this.start, this.end, this.horizontal, this.length, this.positions);
}
So there is no type inference possible here. And strong mode gets worried.
So there are a couple of possibilities to get type inference to work,
factory Car(Position start, bool horizontal, int length) {
var end = horizontal
? start + new Position(length - 1, 0)
: start + new Position(0, length - 1);
var positions = length == 2
? <Position>[start, end]
: horizontal
? <Position>[start, start + new Position(1, 0), end]
: <Position>[start, start + new Position(0, 1), end];
return new Car._(start, end, horizontal, length, positions);
}
static Position _getEnd(Position start, bool horizontal, int length) {
if (horizontal) {
return start + new Position(length - 1, 0);
} else {
return start + new Position(0, length - 1);
}
}
static List<Position> _getPositions(
Position start, bool horizontal, int length, Position end) {
if (length == 2) {
return <Position>[start, end];
} else {
if (horizontal)
return <Position>[start, start + new Position(1, 0), end];
else
return <Position>[start, start + new Position(0, 1), end];
}
}
factory Car(Position start, bool horizontal, int length) {
var end = _getEnd(start, horizontal, length);
var positions = _getPositions(start, horizontal, length, end);
return new Car._(start, end, horizontal, length, positions);
}
Generally, I would not go for this, it is quite much extra chars to type
(annotating all the types of those two functions).
And for two functions that I only use one time, only in the factory
constructor.
There is yet another alternative, which may look a bit ugly, but does a
factory Car(Position start, bool horizontal, int length) {
var end = () {
if (horizontal) {
return start + new Position(length - 1, 0);
} else {
return start + new Position(0, length - 1);
}
}();
var positions = () {
if (length == 2) {
return <Position>[start, end];
} else {
if (horizontal)
return <Position>[start, start + new Position(1, 0), end];
else
return <Position>[start, start + new Position(0, 1), end];
}
}();
return new Car._(start, end, horizontal, length, positions);
}
So, now what style do you guys think fits the job best here, to get
inference working?
I think the problem is, that there is no clear winner. It is also quite
hard to think about some language addition that could give a clear winner
here.
Here is some thought I had today. Basically, allowing the get keyword in
local scope, as some sugar for anonymous functions that immediately execute.
factory Car(Position start, bool horizontal, int length) {
var end = get {
if (horizontal) {
return start + new Position(length - 1, 0);
} else {
return start + new Position(0, length - 1);
}
}
var positions = get {
if (length == 2) {
return [start, end];
} else {
if (horizontal)
return [start, start + new Position(1, 0), end];
else
return [start, start + new Position(0, 1), end];
}
}
return new Car._(start, end, horizontal, length, positions);
}
Any thoughts? Other ideas? And maybe more practically, how would you
write this kind of code using Dart today?
--
For other discussions, see https://groups.google.com/a/dartlang.org/
For HOWTO questions, visit http://stackoverflow.com/tags/dart
To file a bug report or feature request, go to
http://www.dartbug.com/new
---
You received this message because you are subscribed to the Google
Groups "Dart Misc" group.
To unsubscribe from this group and stop receiving emails from it, send
--
Why is this e-mail so short? Answer: five.sentenc.es.
--
For other discussions, see https://groups.google.com/a/dartlang.org/
For HOWTO questions, visit http://stackoverflow.com/tags/dart
To file a bug report or feature request, go to http://www.dartbug.com/new
---
You received this message because you are subscribed to the Google Groups
"Dart Misc" group.
To unsubscribe from this group and stop receiving emails from it, send an
--
For other discussions, see https://groups.google.com/a/dartlang.org/

For HOWTO questions, visit http://stackoverflow.com/tags/dart

To file a bug report or feature request, go to http://www.dartbug.com/new
---
You received this message because you are subscribed to the Google Groups "Dart Misc" group.
To unsubscribe from this group and stop receiving emails from it, send an email to misc+***@dartlang.org.
Kasper Peulen
2015-12-15 09:48:59 UTC
Permalink
Thanks for your response. I think I agree.

Position end;
if (horizontal) {
end = start + new Position(length - 1, 0);
} else {
end = start + new Position(0, length - 1);
}

List<Position> positions;
if (length == 2) {
positions = [start, end];
} else {
if (horizontal)
positions = [start, start + new Position(1, 0), end];
else
positions = [start, start + new Position(0, 1), end];
}


This is probably the neatest solution for now.

I think what I also like about the other solutions I posted, is that I
could make the variables final in this way. I'm also experimenting with
that, making all local variables final if possible.
Post by 'Leaf Petersen' via Dart Misc
We've discussed this issue internally a number of times, and probably will
again. In general we've so far tried to keep our inference fairly simple,
both to avoid programmer surprise, and to avoid committing to
algorithmically more expensive inference. In the general case, Andreas'
suggestion leads to computing a fixed point, since variables may be defined
in terms of other variables (there are of course intermediate points short
of doing the full fixed-point iteration, and points beyond it as well).
This isn't by any means meant to imply that these things can't or shouldn't
be done - just that we've tried to start out fairly conservatively on all
axes with a mind to generalizing where we need to.
My personal take is that for the time being the nicest pattern here is
just to have a convention of left annotating variables that are initialized
conditionally. Note that strong mode will partially make up for the added
verbosity by inferring for you the `<Position>` on the list literals. I
realize that this is a bit of a departure from the preferred style though.
cheers,
-leaf
Post by Kasper Peulen
I think that in strong mode, if you initialize the variable as null, and
you don't add type annotations, the inferred type will always be dynamic.
If I understand it correctly, the inferred type must be determined when
the the variable is initialized. Because otherwise, you are basically,
changing type after creation, and that is exactly what a dynamic variable
does.
The analyzer also keeps track of the "propagated" type, I believe, for
code completion etc, but I believe that this is different concept.
So for example.
var arg;
var arg = <int>[1];
will have propogated type List<int> (you will get code completion for a),
but inferred type is dynamic, and a function that only accepts List<int> as
argument, will not accept `arg` (in strong mode), without a runtime type
check.
Post by 'Andreas Kirsch' via Dart Misc
Imo, we should do a type inference here that works with type
intersections. Ie when we look at the code we should infer the highest
common type denominator and use that for the variable.
Ie if you have
```
var a;
if (...) {
a = 1.0;
} else {
a = 'hello';
}
```
a should be of inferred type Object.
Using type unions or accepting dynamic actually makes automated
refactorings really difficult and creates hidden coupling between different
types.
What do you think?
Thanks,
Andreas
Post by Kasper Peulen
The last couple of weeks, I've been exploring strong mode.
And I try to not left type local variables, but use inference instead.
One type of construct that feels a bit off in this scenario, is
initializing a local variable to null, and do an if ... else ... construct
to calculate the value.
Same for try ... catch kind of constructs.
In this way, there is no type inference possible.
My question is, how do you guys do this? And what would be a good style?
I have here maybe a good example, I'm coding right now. Please don't
put too much attention about the actual code, I just want to give an
class Car {
final Position start;
final Position end;
final bool horizontal;
final int length;
final List<Position> positions;
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);
}
Car._(this.start, this.end, this.horizontal, this.length, this.positions);
}
So there is no type inference possible here. And strong mode gets worried.
So there are a couple of possibilities to get type inference to work,
factory Car(Position start, bool horizontal, int length) {
var end = horizontal
? start + new Position(length - 1, 0)
: start + new Position(0, length - 1);
var positions = length == 2
? <Position>[start, end]
: horizontal
? <Position>[start, start + new Position(1, 0), end]
: <Position>[start, start + new Position(0, 1), end];
return new Car._(start, end, horizontal, length, positions);
}
static Position _getEnd(Position start, bool horizontal, int length) {
if (horizontal) {
return start + new Position(length - 1, 0);
} else {
return start + new Position(0, length - 1);
}
}
static List<Position> _getPositions(
Position start, bool horizontal, int length, Position end) {
if (length == 2) {
return <Position>[start, end];
} else {
if (horizontal)
return <Position>[start, start + new Position(1, 0), end];
else
return <Position>[start, start + new Position(0, 1), end];
}
}
factory Car(Position start, bool horizontal, int length) {
var end = _getEnd(start, horizontal, length);
var positions = _getPositions(start, horizontal, length, end);
return new Car._(start, end, horizontal, length, positions);
}
Generally, I would not go for this, it is quite much extra chars to
type (annotating all the types of those two functions).
And for two functions that I only use one time, only in the factory
constructor.
There is yet another alternative, which may look a bit ugly, but does a
factory Car(Position start, bool horizontal, int length) {
var end = () {
if (horizontal) {
return start + new Position(length - 1, 0);
} else {
return start + new Position(0, length - 1);
}
}();
var positions = () {
if (length == 2) {
return <Position>[start, end];
} else {
if (horizontal)
return <Position>[start, start + new Position(1, 0), end];
else
return <Position>[start, start + new Position(0, 1), end];
}
}();
return new Car._(start, end, horizontal, length, positions);
}
So, now what style do you guys think fits the job best here, to get
inference working?
I think the problem is, that there is no clear winner. It is also quite
hard to think about some language addition that could give a clear winner
here.
Here is some thought I had today. Basically, allowing the get keyword
in local scope, as some sugar for anonymous functions that immediately
execute.
factory Car(Position start, bool horizontal, int length) {
var end = get {
if (horizontal) {
return start + new Position(length - 1, 0);
} else {
return start + new Position(0, length - 1);
}
}
var positions = get {
if (length == 2) {
return [start, end];
} else {
if (horizontal)
return [start, start + new Position(1, 0), end];
else
return [start, start + new Position(0, 1), end];
}
}
return new Car._(start, end, horizontal, length, positions);
}
Any thoughts? Other ideas? And maybe more practically, how would you
write this kind of code using Dart today?
--
For other discussions, see https://groups.google.com/a/dartlang.org/
For HOWTO questions, visit http://stackoverflow.com/tags/dart
To file a bug report or feature request, go to
http://www.dartbug.com/new
---
You received this message because you are subscribed to the Google
Groups "Dart Misc" group.
To unsubscribe from this group and stop receiving emails from it, send
--
Why is this e-mail so short? Answer: five.sentenc.es.
--
For other discussions, see https://groups.google.com/a/dartlang.org/
For HOWTO questions, visit http://stackoverflow.com/tags/dart
To file a bug report or feature request, go to http://www.dartbug.com/new
---
You received this message because you are subscribed to the Google Groups
"Dart Misc" group.
To unsubscribe from this group and stop receiving emails from it, send an
--
For other discussions, see https://groups.google.com/a/dartlang.org/

For HOWTO questions, visit http://stackoverflow.com/tags/dart

To file a bug report or feature request, go to http://www.dartbug.com/new
---
You received this message because you are subscribed to the Google Groups "Dart Misc" group.
To unsubscribe from this group and stop receiving emails from it, send an email to misc+***@dartlang.org.
'John Messerly' via Dart Misc
2015-12-17 17:18:52 UTC
Permalink
BTW, we also have a tracking bug for this:
https://github.com/dart-lang/dev_compiler/issues/70
Post by Kasper Peulen
Thanks for your response. I think I agree.
Position end;
if (horizontal) {
end = start + new Position(length - 1, 0);
} else {
end = start + new Position(0, length - 1);
}
List<Position> positions;
if (length == 2) {
positions = [start, end];
} else {
if (horizontal)
positions = [start, start + new Position(1, 0), end];
else
positions = [start, start + new Position(0, 1), end];
}
This is probably the neatest solution for now.
I think what I also like about the other solutions I posted, is that I
could make the variables final in this way. I'm also experimenting with
that, making all local variables final if possible.
Post by 'Leaf Petersen' via Dart Misc
We've discussed this issue internally a number of times, and probably
will again. In general we've so far tried to keep our inference fairly
simple, both to avoid programmer surprise, and to avoid committing to
algorithmically more expensive inference. In the general case, Andreas'
suggestion leads to computing a fixed point, since variables may be defined
in terms of other variables (there are of course intermediate points short
of doing the full fixed-point iteration, and points beyond it as well).
This isn't by any means meant to imply that these things can't or shouldn't
be done - just that we've tried to start out fairly conservatively on all
axes with a mind to generalizing where we need to.
My personal take is that for the time being the nicest pattern here is
just to have a convention of left annotating variables that are initialized
conditionally. Note that strong mode will partially make up for the added
verbosity by inferring for you the `<Position>` on the list literals. I
realize that this is a bit of a departure from the preferred style though.
cheers,
-leaf
Post by Kasper Peulen
I think that in strong mode, if you initialize the variable as null, and
you don't add type annotations, the inferred type will always be dynamic.
If I understand it correctly, the inferred type must be determined when
the the variable is initialized. Because otherwise, you are basically,
changing type after creation, and that is exactly what a dynamic variable
does.
The analyzer also keeps track of the "propagated" type, I believe, for
code completion etc, but I believe that this is different concept.
So for example.
var arg;
var arg = <int>[1];
will have propogated type List<int> (you will get code completion for
a), but inferred type is dynamic, and a function that only accepts
List<int> as argument, will not accept `arg` (in strong mode), without a
runtime type check.
Post by 'Andreas Kirsch' via Dart Misc
Imo, we should do a type inference here that works with type
intersections. Ie when we look at the code we should infer the highest
common type denominator and use that for the variable.
Ie if you have
```
var a;
if (...) {
a = 1.0;
} else {
a = 'hello';
}
```
a should be of inferred type Object.
Using type unions or accepting dynamic actually makes automated
refactorings really difficult and creates hidden coupling between different
types.
What do you think?
Thanks,
Andreas
Post by Kasper Peulen
The last couple of weeks, I've been exploring strong mode.
And I try to not left type local variables, but use inference instead.
One type of construct that feels a bit off in this scenario, is
initializing a local variable to null, and do an if ... else ... construct
to calculate the value.
Same for try ... catch kind of constructs.
In this way, there is no type inference possible.
My question is, how do you guys do this? And what would be a good style?
I have here maybe a good example, I'm coding right now. Please don't
put too much attention about the actual code, I just want to give an
class Car {
final Position start;
final Position end;
final bool horizontal;
final int length;
final List<Position> positions;
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);
}
Car._(this.start, this.end, this.horizontal, this.length, this.positions);
}
So there is no type inference possible here. And strong mode gets worried.
So there are a couple of possibilities to get type inference to work,
factory Car(Position start, bool horizontal, int length) {
var end = horizontal
? start + new Position(length - 1, 0)
: start + new Position(0, length - 1);
var positions = length == 2
? <Position>[start, end]
: horizontal
? <Position>[start, start + new Position(1, 0), end]
: <Position>[start, start + new Position(0, 1), end];
return new Car._(start, end, horizontal, length, positions);
}
static Position _getEnd(Position start, bool horizontal, int length) {
if (horizontal) {
return start + new Position(length - 1, 0);
} else {
return start + new Position(0, length - 1);
}
}
static List<Position> _getPositions(
Position start, bool horizontal, int length, Position end) {
if (length == 2) {
return <Position>[start, end];
} else {
if (horizontal)
return <Position>[start, start + new Position(1, 0), end];
else
return <Position>[start, start + new Position(0, 1), end];
}
}
factory Car(Position start, bool horizontal, int length) {
var end = _getEnd(start, horizontal, length);
var positions = _getPositions(start, horizontal, length, end);
return new Car._(start, end, horizontal, length, positions);
}
Generally, I would not go for this, it is quite much extra chars to
type (annotating all the types of those two functions).
And for two functions that I only use one time, only in the factory
constructor.
There is yet another alternative, which may look a bit ugly, but does
factory Car(Position start, bool horizontal, int length) {
var end = () {
if (horizontal) {
return start + new Position(length - 1, 0);
} else {
return start + new Position(0, length - 1);
}
}();
var positions = () {
if (length == 2) {
return <Position>[start, end];
} else {
if (horizontal)
return <Position>[start, start + new Position(1, 0), end];
else
return <Position>[start, start + new Position(0, 1), end];
}
}();
return new Car._(start, end, horizontal, length, positions);
}
So, now what style do you guys think fits the job best here, to get
inference working?
I think the problem is, that there is no clear winner. It is also
quite hard to think about some language addition that could give a clear
winner here.
Here is some thought I had today. Basically, allowing the get keyword
in local scope, as some sugar for anonymous functions that immediately
execute.
factory Car(Position start, bool horizontal, int length) {
var end = get {
if (horizontal) {
return start + new Position(length - 1, 0);
} else {
return start + new Position(0, length - 1);
}
}
var positions = get {
if (length == 2) {
return [start, end];
} else {
if (horizontal)
return [start, start + new Position(1, 0), end];
else
return [start, start + new Position(0, 1), end];
}
}
return new Car._(start, end, horizontal, length, positions);
}
Any thoughts? Other ideas? And maybe more practically, how would you
write this kind of code using Dart today?
--
For other discussions, see https://groups.google.com/a/dartlang.org/
For HOWTO questions, visit http://stackoverflow.com/tags/dart
To file a bug report or feature request, go to
http://www.dartbug.com/new
---
You received this message because you are subscribed to the Google
Groups "Dart Misc" group.
To unsubscribe from this group and stop receiving emails from it, send
--
Why is this e-mail so short? Answer: five.sentenc.es.
--
For other discussions, see https://groups.google.com/a/dartlang.org/
For HOWTO questions, visit http://stackoverflow.com/tags/dart
To file a bug report or feature request, go to
http://www.dartbug.com/new
---
You received this message because you are subscribed to the Google
Groups "Dart Misc" group.
To unsubscribe from this group and stop receiving emails from it, send
--
For other discussions, see https://groups.google.com/a/dartlang.org/
For HOWTO questions, visit http://stackoverflow.com/tags/dart
To file a bug report or feature request, go to http://www.dartbug.com/new
---
You received this message because you are subscribed to the Google Groups
"Dart Misc" group.
To unsubscribe from this group and stop receiving emails from it, send an
--
For other discussions, see https://groups.google.com/a/dartlang.org/

For HOWTO questions, visit http://stackoverflow.com/tags/dart

To file a bug report or feature request, go to http://www.dartbug.com/new
---
You received this message because you are subscribed to the Google Groups "Dart Misc" group.
To unsubscribe from this group and stop receiving emails from it, send an email to misc+***@dartlang.org.
'Bob Nystrom' via Dart Misc
2015-12-17 17:34:34 UTC
Permalink
Oh, wow. It's nice showing up late to a thread full of well thought-out
approaches. :)

Kasper, I think your list of patterns is pretty much the exhaustive set of
options on how to handle this in Dart today. You even came up with the
"immediately invoked local function" one. :)

I agree with Leaf that it would be nice to avoid flow-based inference if
possible since it can be some combination of a Pandora's box / can of worms
/ rathole. Maybe a Pandora's wormhole.

If we put language changes on the table, there is one that comes to mind:

*Allow if and possibly other control flow statements to be used as
expressions.*

var positions = if (length == 2) {
[start, end];
} else {
if (horizontal)
[start, start + new Position(1, 0), end];
else
[start, start + new Position(0, 1), end];
}


The functional programmer in me finds this appealing and it would mean
adding a minimum of new syntax. But it looks, well, weird in a language
with a C-derived syntax like Dart. Having a bare value like these list
literals sitting in statement position and have that actually do something
useful is quite a departure from C/C++/Java/C#/JS/etc.

Strangely, I feel this would be more palatable if we made semicolons
optional because that's enough of a visual kick to get you out of the
heavily statement-based mindset of C, but even so this might be weird. My
current feeling is that it wouldn't be a good fit for Dart. (And, even if
it would work out well, I don't think it would be possible to convince the
language team to go for it.)

There are a lot of similar cases where it's hard to infer a local variable
type that would be helped by adding some kind of pattern matching syntax.
That wouldn't help here, though, unless we also made the pattern matching
construct an expression instead of a statement. I think that's about as
likely as making if () an expression.

In this *specific* case, there's an easy solution:

var positions = [start, end];
if (length != 2) {
if (horizontal) {
positions.insert(1, start + new Position(1, 0));
} else {
positions.insert(1, start + new Position(0, 1));
}
}

:)

– bob


On Thu, Dec 17, 2015 at 9:18 AM, 'John Messerly' via Dart Misc <
Post by 'John Messerly' via Dart Misc
https://github.com/dart-lang/dev_compiler/issues/70
Post by Kasper Peulen
Thanks for your response. I think I agree.
Position end;
if (horizontal) {
end = start + new Position(length - 1, 0);
} else {
end = start + new Position(0, length - 1);
}
List<Position> positions;
if (length == 2) {
positions = [start, end];
} else {
if (horizontal)
positions = [start, start + new Position(1, 0), end];
else
positions = [start, start + new Position(0, 1), end];
}
This is probably the neatest solution for now.
I think what I also like about the other solutions I posted, is that I
could make the variables final in this way. I'm also experimenting with
that, making all local variables final if possible.
Post by 'Leaf Petersen' via Dart Misc
We've discussed this issue internally a number of times, and probably
will again. In general we've so far tried to keep our inference fairly
simple, both to avoid programmer surprise, and to avoid committing to
algorithmically more expensive inference. In the general case, Andreas'
suggestion leads to computing a fixed point, since variables may be defined
in terms of other variables (there are of course intermediate points short
of doing the full fixed-point iteration, and points beyond it as well).
This isn't by any means meant to imply that these things can't or shouldn't
be done - just that we've tried to start out fairly conservatively on all
axes with a mind to generalizing where we need to.
My personal take is that for the time being the nicest pattern here is
just to have a convention of left annotating variables that are initialized
conditionally. Note that strong mode will partially make up for the added
verbosity by inferring for you the `<Position>` on the list literals. I
realize that this is a bit of a departure from the preferred style though.
cheers,
-leaf
Post by Kasper Peulen
I think that in strong mode, if you initialize the variable as null,
and you don't add type annotations, the inferred type will always be
dynamic.
If I understand it correctly, the inferred type must be determined when
the the variable is initialized. Because otherwise, you are basically,
changing type after creation, and that is exactly what a dynamic variable
does.
The analyzer also keeps track of the "propagated" type, I believe, for
code completion etc, but I believe that this is different concept.
So for example.
var arg;
var arg = <int>[1];
will have propogated type List<int> (you will get code completion for
a), but inferred type is dynamic, and a function that only accepts
List<int> as argument, will not accept `arg` (in strong mode), without a
runtime type check.
Post by 'Andreas Kirsch' via Dart Misc
Imo, we should do a type inference here that works with type
intersections. Ie when we look at the code we should infer the highest
common type denominator and use that for the variable.
Ie if you have
```
var a;
if (...) {
a = 1.0;
} else {
a = 'hello';
}
```
a should be of inferred type Object.
Using type unions or accepting dynamic actually makes automated
refactorings really difficult and creates hidden coupling between different
types.
What do you think?
Thanks,
Andreas
Post by Kasper Peulen
The last couple of weeks, I've been exploring strong mode.
And I try to not left type local variables, but use inference instead.
One type of construct that feels a bit off in this scenario, is
initializing a local variable to null, and do an if ... else ... construct
to calculate the value.
Same for try ... catch kind of constructs.
In this way, there is no type inference possible.
My question is, how do you guys do this? And what would be a good style?
I have here maybe a good example, I'm coding right now. Please don't
put too much attention about the actual code, I just want to give an
class Car {
final Position start;
final Position end;
final bool horizontal;
final int length;
final List<Position> positions;
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);
}
Car._(this.start, this.end, this.horizontal, this.length, this.positions);
}
So there is no type inference possible here. And strong mode gets worried.
So there are a couple of possibilities to get type inference to work,
factory Car(Position start, bool horizontal, int length) {
var end = horizontal
? start + new Position(length - 1, 0)
: start + new Position(0, length - 1);
var positions = length == 2
? <Position>[start, end]
: horizontal
? <Position>[start, start + new Position(1, 0), end]
: <Position>[start, start + new Position(0, 1), end];
return new Car._(start, end, horizontal, length, positions);
}
static Position _getEnd(Position start, bool horizontal, int length) {
if (horizontal) {
return start + new Position(length - 1, 0);
} else {
return start + new Position(0, length - 1);
}
}
static List<Position> _getPositions(
Position start, bool horizontal, int length, Position end) {
if (length == 2) {
return <Position>[start, end];
} else {
if (horizontal)
return <Position>[start, start + new Position(1, 0), end];
else
return <Position>[start, start + new Position(0, 1), end];
}
}
factory Car(Position start, bool horizontal, int length) {
var end = _getEnd(start, horizontal, length);
var positions = _getPositions(start, horizontal, length, end);
return new Car._(start, end, horizontal, length, positions);
}
Generally, I would not go for this, it is quite much extra chars to
type (annotating all the types of those two functions).
And for two functions that I only use one time, only in the factory
constructor.
There is yet another alternative, which may look a bit ugly, but does
factory Car(Position start, bool horizontal, int length) {
var end = () {
if (horizontal) {
return start + new Position(length - 1, 0);
} else {
return start + new Position(0, length - 1);
}
}();
var positions = () {
if (length == 2) {
return <Position>[start, end];
} else {
if (horizontal)
return <Position>[start, start + new Position(1, 0), end];
else
return <Position>[start, start + new Position(0, 1), end];
}
}();
return new Car._(start, end, horizontal, length, positions);
}
So, now what style do you guys think fits the job best here, to get
inference working?
I think the problem is, that there is no clear winner. It is also
quite hard to think about some language addition that could give a clear
winner here.
Here is some thought I had today. Basically, allowing the get keyword
in local scope, as some sugar for anonymous functions that immediately
execute.
factory Car(Position start, bool horizontal, int length) {
var end = get {
if (horizontal) {
return start + new Position(length - 1, 0);
} else {
return start + new Position(0, length - 1);
}
}
var positions = get {
if (length == 2) {
return [start, end];
} else {
if (horizontal)
return [start, start + new Position(1, 0), end];
else
return [start, start + new Position(0, 1), end];
}
}
return new Car._(start, end, horizontal, length, positions);
}
Any thoughts? Other ideas? And maybe more practically, how would you
write this kind of code using Dart today?
--
For other discussions, see https://groups.google.com/a/dartlang.org/
For HOWTO questions, visit http://stackoverflow.com/tags/dart
To file a bug report or feature request, go to
http://www.dartbug.com/new
---
You received this message because you are subscribed to the Google
Groups "Dart Misc" group.
To unsubscribe from this group and stop receiving emails from it,
--
Why is this e-mail so short? Answer: five.sentenc.es.
--
For other discussions, see https://groups.google.com/a/dartlang.org/
For HOWTO questions, visit http://stackoverflow.com/tags/dart
To file a bug report or feature request, go to
http://www.dartbug.com/new
---
You received this message because you are subscribed to the Google
Groups "Dart Misc" group.
To unsubscribe from this group and stop receiving emails from it, send
--
For other discussions, see https://groups.google.com/a/dartlang.org/
For HOWTO questions, visit http://stackoverflow.com/tags/dart
To file a bug report or feature request, go to http://www.dartbug.com/new
---
You received this message because you are subscribed to the Google Groups
"Dart Misc" group.
To unsubscribe from this group and stop receiving emails from it, send an
--
For other discussions, see https://groups.google.com/a/dartlang.org/
For HOWTO questions, visit http://stackoverflow.com/tags/dart
To file a bug report or feature request, go to http://www.dartbug.com/new
---
You received this message because you are subscribed to the Google Groups
"Dart Misc" group.
To unsubscribe from this group and stop receiving emails from it, send an
--
For other discussions, see https://groups.google.com/a/dartlang.org/

For HOWTO questions, visit http://stackoverflow.com/tags/dart

To file a bug report or feature request, go to http://www.dartbug.com/new
---
You received this message because you are subscribed to the Google Groups "Dart Misc" group.
To unsubscribe from this group and stop receiving emails from it, send an email to misc+***@dartlang.org.
'Lasse R.H. Nielsen' via Dart Misc
2015-12-17 18:05:08 UTC
Permalink
On Thu, Dec 17, 2015 at 6:34 PM, 'Bob Nystrom' via Dart Misc <
Post by 'Bob Nystrom' via Dart Misc
Oh, wow. It's nice showing up late to a thread full of well thought-out
approaches. :)
Kasper, I think your list of patterns is pretty much the exhaustive set of
options on how to handle this in Dart today. You even came up with the
"immediately invoked local function" one. :)
I agree with Leaf that it would be nice to avoid flow-based inference if
possible since it can be some combination of a Pandora's box / can of worms
/ rathole. Maybe a Pandora's wormhole.
*Allow if and possibly other control flow statements to be used as
expressions.*
var positions = if (length == 2) {
[start, end];
} else {
if (horizontal)
[start, start + new Position(1, 0), end];
else
[start, start + new Position(0, 1), end];
}
I think this has been brought up before.
We already have "if" for expressions, it's the conditional expression
c?e1:e2. It can write the code above without a problem.

The difference here is probably that you want to be able to add statements
as well, so you have a statement that evaluates to a value. That can be
solved by a "statement-expression" construct. I don't have a good syntax,
so let's say something like ::stmt::expr.
That is completely general and allows any statement to be used in an
expression, it just needs to be finished off with an expression so it
evaluates to a value.

(It's not without complications when every expression can contain a return
or break statement, there are places in the semantics and in the compilers
where it's used that the only non-local control flow you can do in an
expression is throw).

/L
--
Lasse R.H. Nielsen - ***@google.com
'Faith without judgement merely degrades the spirit divine'
Google Denmark ApS - Frederiksborggade 20B, 1 sal - 1360 KÞbenhavn K
- Denmark - CVR nr. 28 86 69 84
--
For other discussions, see https://groups.google.com/a/dartlang.org/

For HOWTO questions, visit http://stackoverflow.com/tags/dart

To file a bug report or feature request, go to http://www.dartbug.com/new
---
You received this message because you are subscribed to the Google Groups "Dart Misc" group.
To unsubscribe from this group and stop receiving emails from it, send an email to misc+***@dartlang.org.
'Bob Nystrom' via Dart Misc
2015-12-17 18:46:42 UTC
Permalink
On Thu, Dec 17, 2015 at 10:05 AM, 'Lasse R.H. Nielsen' via Dart Misc <
Post by 'Lasse R.H. Nielsen' via Dart Misc
The difference here is probably that you want to be able to add statements
as well, so you have a statement that evaluates to a value. That can be
solved by a "statement-expression" construct. I don't have a good syntax,
so let's say something like ::stmt::expr.
We have that already, it's spelled (){ 
 }()

:)

– bob
--
For other discussions, see https://groups.google.com/a/dartlang.org/

For HOWTO questions, visit http://stackoverflow.com/tags/dart

To file a bug report or feature request, go to http://www.dartbug.com/new
---
You received this message because you are subscribed to the Google Groups "Dart Misc" group.
To unsubscribe from this group and stop receiving emails from it, send an email to misc+***@dartlang.org.
'Lasse R.H. Nielsen' via Dart Misc
2015-12-18 07:13:47 UTC
Permalink
On Thu, Dec 17, 2015 at 7:46 PM, 'Bob Nystrom' via Dart Misc <
Post by 'Bob Nystrom' via Dart Misc
On Thu, Dec 17, 2015 at 10:05 AM, 'Lasse R.H. Nielsen' via Dart Misc <
Post by 'Lasse R.H. Nielsen' via Dart Misc
The difference here is probably that you want to be able to add
statements as well, so you have a statement that evaluates to a value. That
can be solved by a "statement-expression" construct. I don't have a good
syntax, so let's say something like ::stmt::expr.
We have that already, it's spelled (){ 
 }()
:)
True in many cases, but not all.

The exceptions are when the statements contain control flow
(break/continue/return/rethrow) or yield, or when the statements or
expression contains await - then the function needs to be async too, and
you need to await its result, and it'll still delay parts of the code that
would otherwise have been run immediately.

I think that immediate function calls are probably good enough in practice.
If you really want to do a continue in an expression, you should probably
rewrite your code. The cases where you can't rewrite to statements, like
initializer lists, don't allow control flow anyway.

/L
--
Lasse R.H. Nielsen - ***@google.com
'Faith without judgement merely degrades the spirit divine'
Google Denmark ApS - Frederiksborggade 20B, 1 sal - 1360 KÞbenhavn K
- Denmark - CVR nr. 28 86 69 84
--
For other discussions, see https://groups.google.com/a/dartlang.org/

For HOWTO questions, visit http://stackoverflow.com/tags/dart

To file a bug report or feature request, go to http://www.dartbug.com/new
---
You received this message because you are subscribed to the Google Groups "Dart Misc" group.
To unsubscribe from this group and stop receiving emails from it, send an email to misc+***@dartlang.org.
Continue reading on narkive:
Loading...