Discussion:
[dart-misc] doubts about "PREFER using var without a type annotation for local variables." style guide
Kasper Peulen
2015-07-09 01:03:14 UTC
Permalink
PREFER using var without a type annotation for local variables.
Method bodies in modern code tend to be short, and the types of local
variables are almost always trivially inferrable from the initializing
expression, so explicit type annotations are usually just visual noise.
Decent editors can infer the type of local variables and still provide the
auto-complete and tooling support you expect.
Okay here are my reason why I think 1) type annotations are not "usually
just visual noise" and why I think that 2) you don't get the "tooling
support you expect".

1. Let's consider the following code from the pub package:

var pubspecs = await source.getVersions(package, package);
var versions = pubspecs.map((pubspec) => pubspec.version).where(constraint.
allows).toList();

If we would add types, we get:

List<Pubspec> pubspecs = await source.getVersions(package, package);
List<Version> versions = pubspecs.map((pubspec) => pubspec.version)
.where(constraint.allows).toList();

I think this improves readability of the code. And it also improves
explorability of the library apis. Now I can just press F1 on the Pubspec
and Version class, to see what the docs say.
I can go to the declaration of the Pubspec and Version class easily to
learn more about those classes.

But also code like this:

var directories = pluralize('Directory', directoryNames.length, plural:
'Directories');
var names = toSentence(directoryNames.map((dir) => '"$dir"'));
var verb = pluralize(singularVerb, directoryNames.length, plural: pluralVerb
);

It is just 2 chars longer to write:

String directories = pluralize('Directory', directoryNames.length, plural:
'Directories');
String names = toSentence(directoryNames.map((dir) => '"$dir"'));
String verb = pluralize(singularVerb, directoryNames.length, plural:
pluralVerb);

Why wouldn't you give those extra hints to your reader ? Now I have to
first read the docs about those methods, to see what it returns.
Maybe if I'm smart I can understand it from the names that are chosen, but
surely not in every case, and it will usually take longer for the reader to
infer the types from the method names then if you just add a friendly type.

2. Then you also have examples like var input = new InputElement(); where
it doesn't really add anything for readability if you would write
InputElement input = new InputElement();

But there is also another argument for adding type annotation, and that is
just that the analyser gets smarter the more type annotations you add. Say
we have a class MathInput that extends the InputElement class, with a
method called mathValue. Now if you write:

var input = new InputElement()
input.mathValue = "\pi = 3.1415...";

You wan't get any errors or warnings for this. See:
https://dartpad.dartlang.org/f2ade932d2aa7a3dfe85 But of course, the
program will fail if you run it. stereotype441 from the analyser team told
me this is the reason that the analyser don't give a warning:

The reason the analyzer doesn't give a hint for the call to foo2() is
because when the user declares a variable using "var" or "dynamic", they're
essentially saying to the toolchain "trust me, I know what I'm doing with
this variable, and I don't want to see warnings for it." We don't want to
give them a spurious hint unless we are really certain that the call is not
going to work.
see: https://github.com/dart-lang/dart-pad/issues/302#issuecomment-91373539

My reasoning is, if you know that the variable is a InputElement, and you
know that it will never be any other type, why leave the analyser in doubt
? Why would you give the analyser the signal: "trust me, I know what I'm
doing with this variable, and I don't want to see warnings for it." ?

I won't argue that the style guide should change to "PREFER using types for
local variables", I think it is great in dart that you have the choice to
use the `var` keyword if this makes sense. In the example of the style
guide:
Map<int, List<Person>> peopleByZip = new Map<int, List<Person>>();

Here I see that using types gives extra noise. But I don't see the point of
dogmatically avoiding any types for local variables. Which seems the case
in some dart projects that I open. I would say PREFER using types CONSIDER
using `var` if the type doesn't improve readability and gives extra visual
noise.
--
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

To unsubscribe from this group and stop receiving emails from it, send an email to misc+***@dartlang.org.
Peter StJ
2015-07-09 10:01:03 UTC
Permalink
I almost always use types where 'var' is preferred even if it makes the
code noisier, the main reason being the better auto-completion and docs
hinting / viewing. Event when the analyzer correctly figures out the type
of 'var' the number of cases where it does not is much larger in my own
experience (this is - I might be writing bad code (from analyzer's
perspective)) so instead of guessing and going back I just always write
down the type. It also prevents me from doing stupid things when going too
fast (like putting something else in the var, different from what I was
intending originally).

That said - the recommendation never stopped me, I just ignore the parts of
it I do not consider useful in my practice. Another such ignored part that
seem to be large in google is the number of columns used in the code - it
simply does not make sense in dart because of the semantics of the arrow
function.
PREFER using var without a type annotation for local variables.
Method bodies in modern code tend to be short, and the types of local
variables are almost always trivially inferrable from the initializing
expression, so explicit type annotations are usually just visual noise.
Decent editors can infer the type of local variables and still provide the
auto-complete and tooling support you expect.
Okay here are my reason why I think 1) type annotations are not "usually
just visual noise" and why I think that 2) you don't get the "tooling
support you expect".
var pubspecs = await source.getVersions(package, package);
var versions = pubspecs.map((pubspec) => pubspec.version).where(constraint
.allows).toList();
List<Pubspec> pubspecs = await source.getVersions(package, package);
List<Version> versions = pubspecs.map((pubspec) => pubspec.version).where(
constraint.allows).toList();
I think this improves readability of the code. And it also improves
explorability of the library apis. Now I can just press F1 on the Pubspec
and Version class, to see what the docs say.
I can easily go to the declaration of the Pubspec and Version class to
learn more about those classes.
'Directories');
var names = toSentence(directoryNames.map((dir) => '"$dir"'));
pluralVerb);
'Directories');
String names = toSentence(directoryNames.map((dir) => '"$dir"'));
pluralVerb);
Why wouldn't you give those extra hints to your reader ? Now I have to
first read the docs about those methods, to see what it returns.
Maybe if I'm smart I can understand it from the names that are chosen, but
surely not in every case, and it will usually take longer for the reader to
infer the types from the method names then if you just add a friendly type.
2. Then you also have examples like var input = new InputElement(); where
it doesn't really add anything for readability if you would write
InputElement input = new InputElement();
But there is also another argument for adding type annotation, and that is
just that the analyser gets smarter the more type annotations you add. Say
we have a class MathInput that extends the InputElement class, with a
var input = new InputElement()
input.mathValue = "\pi = 3.1415...";
https://dartpad.dartlang.org/f2ade932d2aa7a3dfe85 But of course, the
program will fail if you run it. stereotype441 from the analyser team told
The reason the analyzer doesn't give a hint for the call to foo2() is
because when the user declares a variable using "var" or "dynamic", they're
essentially saying to the toolchain "trust me, I know what I'm doing with
this variable, and I don't want to see warnings for it." We don't want to
give them a spurious hint unless we are really certain that the call is not
going to work.
https://github.com/dart-lang/dart-pad/issues/302#issuecomment-91373539
My reasoning is, if you know that the variable is a InputElement, and you
know that it will never be any other type, why leave the analyser in doubt
? Why would you give the analyser the signal: "trust me, I know what I'm
doing with this variable, and I don't want to see warnings for it." ?
I won't argue that the style guide should change to "PREFER using types
always and everywhere", I think it is great in dart that you have the
choice to use the `var` keyword if this makes sense. In the example of the
Map<int, List<Person>> peopleByZip = new Map<int, List<Person>>();
Here I see that using types gives extra noise. But I don't see the point
of dogmatically avoiding any types for local variables. Which seems the
case in some dart projects that I open. I would say PREFER using types for
local variables CONSIDER using `var` if the type doesn't improve
readability and gives extra visual noise.
--
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

To unsubscribe from this group and stop receiving emails from it, send an email to misc+***@dartlang.org.
Daniel Joyce
2015-07-09 14:29:49 UTC
Permalink
Darts type system and inferencing is simply not strong enough to allow
using var in place of explicit types. Been bitten by this a few times. Too
javascripty. As others have noted it passes the analyzer but fails at
runtime. For this to work the analyzer needs to be stricter.

I use types everywhere when I can. Too many JavaScript style stupid type
bugs when I don't. This reccomendation of using var all the time only works
in a strong staticly typed language with inferencing, like Scala.
Post by Peter StJ
I almost always use types where 'var' is preferred even if it makes the
code noisier, the main reason being the better auto-completion and docs
hinting / viewing. Event when the analyzer correctly figures out the type
of 'var' the number of cases where it does not is much larger in my own
experience (this is - I might be writing bad code (from analyzer's
perspective)) so instead of guessing and going back I just always write
down the type. It also prevents me from doing stupid things when going too
fast (like putting something else in the var, different from what I was
intending originally).
That said - the recommendation never stopped me, I just ignore the parts
of it I do not consider useful in my practice. Another such ignored part
that seem to be large in google is the number of columns used in the code -
it simply does not make sense in dart because of the semantics of the arrow
function.
PREFER using var without a type annotation for local variables.
Method bodies in modern code tend to be short, and the types of local
variables are almost always trivially inferrable from the initializing
expression, so explicit type annotations are usually just visual noise.
Decent editors can infer the type of local variables and still provide the
auto-complete and tooling support you expect.
Okay here are my reason why I think 1) type annotations are not "usually
just visual noise" and why I think that 2) you don't get the "tooling
support you expect".
var pubspecs = await source.getVersions(package, package);
var versions = pubspecs.map((pubspec) => pubspec.version).where(
constraint.allows).toList();
List<Pubspec> pubspecs = await source.getVersions(package, package);
List<Version> versions = pubspecs.map((pubspec) => pubspec.version).where
(constraint.allows).toList();
I think this improves readability of the code. And it also improves
explorability of the library apis. Now I can just press F1 on the Pubspec
and Version class, to see what the docs say.
I can easily go to the declaration of the Pubspec and Version class to
learn more about those classes.
'Directories');
var names = toSentence(directoryNames.map((dir) => '"$dir"'));
pluralVerb);
String directories = pluralize('Directory', directoryNames.length, plural
: 'Directories');
String names = toSentence(directoryNames.map((dir) => '"$dir"'));
pluralVerb);
Why wouldn't you give those extra hints to your reader ? Now I have to
first read the docs about those methods, to see what it returns.
Maybe if I'm smart I can understand it from the names that are chosen,
but surely not in every case, and it will usually take longer for the
reader to infer the types from the method names then if you just add a
friendly type.
2. Then you also have examples like var input = new InputElement(); where
it doesn't really add anything for readability if you would write
InputElement input = new InputElement();
But there is also another argument for adding type annotation, and that
is just that the analyser gets smarter the more type annotations you add.
Say we have a class MathInput that extends the InputElement class, with a
var input = new InputElement()
input.mathValue = "\pi = 3.1415...";
https://dartpad.dartlang.org/f2ade932d2aa7a3dfe85 But of course, the
program will fail if you run it. stereotype441 from the analyser team told
The reason the analyzer doesn't give a hint for the call to foo2() is
because when the user declares a variable using "var" or "dynamic", they're
essentially saying to the toolchain "trust me, I know what I'm doing with
this variable, and I don't want to see warnings for it." We don't want to
give them a spurious hint unless we are really certain that the call is not
going to work.
https://github.com/dart-lang/dart-pad/issues/302#issuecomment-91373539
My reasoning is, if you know that the variable is a InputElement, and you
know that it will never be any other type, why leave the analyser in doubt
? Why would you give the analyser the signal: "trust me, I know what I'm
doing with this variable, and I don't want to see warnings for it." ?
I won't argue that the style guide should change to "PREFER using types
always and everywhere", I think it is great in dart that you have the
choice to use the `var` keyword if this makes sense. In the example of the
Map<int, List<Person>> peopleByZip = new Map<int, List<Person>>();
Here I see that using types gives extra noise. But I don't see the point
of dogmatically avoiding any types for local variables. Which seems the
case in some dart projects that I open. I would say PREFER using types for
local variables CONSIDER using `var` if the type doesn't improve
readability and gives extra visual noise.
--
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
To unsubscribe from this group and stop receiving emails from it, send an
--
Daniel Joyce

The meek shall inherit the Earth, for the brave will be among the stars.
--
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

To unsubscribe from this group and stop receiving emails from it, send an email to misc+***@dartlang.org.
DoHyung Kim
2015-07-09 14:51:43 UTC
Permalink
Having encountered too many cases where the analyzer fails to infer types
of vars (even in the case where it is quite obvious to me), I also have
been very curious if others are happily following the rule. In my case, I
usually try to keep the rule but specify types when inevitable. As you all
expect, a little bit ugly when var and types are mixed.
Post by Peter StJ
I almost always use types where 'var' is preferred even if it makes the
code noisier, the main reason being the better auto-completion and docs
hinting / viewing. Event when the analyzer correctly figures out the type
of 'var' the number of cases where it does not is much larger in my own
experience (this is - I might be writing bad code (from analyzer's
perspective)) so instead of guessing and going back I just always write
down the type. It also prevents me from doing stupid things when going too
fast (like putting something else in the var, different from what I was
intending originally).
That said - the recommendation never stopped me, I just ignore the parts
of it I do not consider useful in my practice. Another such ignored part
that seem to be large in google is the number of columns used in the code -
it simply does not make sense in dart because of the semantics of the arrow
function.
PREFER using var without a type annotation for local variables.
Method bodies in modern code tend to be short, and the types of local
variables are almost always trivially inferrable from the initializing
expression, so explicit type annotations are usually just visual noise.
Decent editors can infer the type of local variables and still provide the
auto-complete and tooling support you expect.
Okay here are my reason why I think 1) type annotations are not "usually
just visual noise" and why I think that 2) you don't get the "tooling
support you expect".
var pubspecs = await source.getVersions(package, package);
var versions = pubspecs.map((pubspec) => pubspec.version).where(
constraint.allows).toList();
List<Pubspec> pubspecs = await source.getVersions(package, package);
List<Version> versions = pubspecs.map((pubspec) => pubspec.version).where
(constraint.allows).toList();
I think this improves readability of the code. And it also improves
explorability of the library apis. Now I can just press F1 on the Pubspec
and Version class, to see what the docs say.
I can easily go to the declaration of the Pubspec and Version class to
learn more about those classes.
'Directories');
var names = toSentence(directoryNames.map((dir) => '"$dir"'));
pluralVerb);
String directories = pluralize('Directory', directoryNames.length, plural
: 'Directories');
String names = toSentence(directoryNames.map((dir) => '"$dir"'));
pluralVerb);
Why wouldn't you give those extra hints to your reader ? Now I have to
first read the docs about those methods, to see what it returns.
Maybe if I'm smart I can understand it from the names that are chosen,
but surely not in every case, and it will usually take longer for the
reader to infer the types from the method names then if you just add a
friendly type.
2. Then you also have examples like var input = new InputElement(); where
it doesn't really add anything for readability if you would write
InputElement input = new InputElement();
But there is also another argument for adding type annotation, and that
is just that the analyser gets smarter the more type annotations you add.
Say we have a class MathInput that extends the InputElement class, with a
var input = new InputElement()
input.mathValue = "\pi = 3.1415...";
https://dartpad.dartlang.org/f2ade932d2aa7a3dfe85 But of course, the
program will fail if you run it. stereotype441 from the analyser team told
The reason the analyzer doesn't give a hint for the call to foo2() is
because when the user declares a variable using "var" or "dynamic", they're
essentially saying to the toolchain "trust me, I know what I'm doing with
this variable, and I don't want to see warnings for it." We don't want to
give them a spurious hint unless we are really certain that the call is not
going to work.
https://github.com/dart-lang/dart-pad/issues/302#issuecomment-91373539
My reasoning is, if you know that the variable is a InputElement, and you
know that it will never be any other type, why leave the analyser in doubt
? Why would you give the analyser the signal: "trust me, I know what I'm
doing with this variable, and I don't want to see warnings for it." ?
I won't argue that the style guide should change to "PREFER using types
always and everywhere", I think it is great in dart that you have the
choice to use the `var` keyword if this makes sense. In the example of the
Map<int, List<Person>> peopleByZip = new Map<int, List<Person>>();
Here I see that using types gives extra noise. But I don't see the point
of dogmatically avoiding any types for local variables. Which seems the
case in some dart projects that I open. I would say PREFER using types for
local variables CONSIDER using `var` if the type doesn't improve
readability and gives extra visual noise.
--
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

To unsubscribe from this group and stop receiving emails from it, send an email to misc+***@dartlang.org.
'Bob Nystrom' via Dart Misc
2015-07-09 17:38:33 UTC
Permalink
Post by Kasper Peulen
List<Pubspec> pubspecs = await source.getVersions(package, package);
List<Version> versions = pubspecs.map((pubspec) => pubspec.version)
.where(constraint.allows).toList();
Technically, that still isn't fully typed, since you didn't type the lambda
parameter. :)
Post by Kasper Peulen
I think this improves readability of the code. And it also improves
explorability of the library apis. Now I can just press F1 on the Pubspec
and Version class, to see what the docs say.
True. But even with var, you can just Go to Definition on getVersions() and
then Go to Definition on the declared return type there. I don't think
there's a real usability win to having the return type annotated.

Even if you do annotate your local variables, there are still many places
where a type isn't explicitly annotated. There's no one-click way to
navigate to the declaration of the return type of pubspec.version or
constraint.allows, or the type of source or pubspecs.

You still have tons of subexpressions whose type isn't written out in the
code, so I don't think it adds much value to treat expressions that happen
to initialize local variables specially.
Post by Kasper Peulen
'Directories');
var names = toSentence(directoryNames.map((dir) => '"$dir"'));
pluralVerb);
'Directories');
String names = toSentence(directoryNames.map((dir) => '"$dir"'));
pluralVerb);
Well, three characters. But that's because these happen to have a
particularly short type name. It's hard to generalize from this.

Why wouldn't you give those extra hints to your reader?
The reader *has* those hints. They can just hover over any of these
function calls to see them.

What I don't think its worth doing is baking that into the source text. I
look at this as extension of the DRY
<https://en.wikipedia.org/wiki/Don't_repeat_yourself> principle. If the
type can be statically determined from the initializer, it is strictly
redundant to also spell it out in the code.
Post by Kasper Peulen
2. Then you also have examples like var input = new InputElement(); where
it doesn't really add anything for readability if you would write
InputElement input = new InputElement();
But there is also another argument for adding type annotation, and that is
just that the analyser gets smarter the more type annotations you add.
I believe the opposite is true. I think the analyzer—the implementation of
the analyzer—gets *dumber* the more annotations we add. The more we use var,
the more pressure we place on the analyzer to do very smart analysis. If we
start annotating everything everywhere, there's no motivation for the
analyzer team to implement any kind of inference.

I think it's *very* important for a modern language with a static type
system to have a strong inference story. Haskell, F#, Go, Rust, Scala, C++,
C#, Kotlin, and Nim all have robust inference for local variables. Now that
most programmers have some familiarity with the terseness of dynamically
typed languages, I don't believe a statically-typed language can be
successful without reliable local variable inference.

Can you point to a statically-typed language that came out in the past
decade, has a decent user base, and *doesn't* do local variable inference?

Say we have a class MathInput that extends the InputElement class, with a
Post by Kasper Peulen
var input = new InputElement()
input.mathValue = "\pi = 3.1415...";
https://dartpad.dartlang.org/f2ade932d2aa7a3dfe85 But of course, the
program will fail if you run it. stereotype441 from the analyser team told
The reason the analyzer doesn't give a hint for the call to foo2() is
because when the user declares a variable using "var" or "dynamic", they're
essentially saying to the toolchain "trust me, I know what I'm doing with
this variable, and I don't want to see warnings for it." We don't want to
give them a spurious hint unless we are really certain that the call is not
going to work.
https://github.com/dart-lang/dart-pad/issues/302#issuecomment-91373539
My reasoning is, if you know that the variable is a InputElement, and you
know that it will never be any other type, why leave the analyser in doubt
? Why would you give the analyser the signal: "trust me, I know what I'm
doing with this variable, and I don't want to see warnings for it." ?
I think implicit downcasting is a misfeature in the language. Either way,
the analyzer could be smarter here and provide a hint.

Here I see that using types gives extra noise. But I don't see the point of
Post by Kasper Peulen
dogmatically avoiding any types for local variables.
It's not dogmatic. That's why the guideline is "PREFER", not "DO".

Cheers!

- 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

To unsubscribe from this group and stop receiving emails from it, send an email to misc+***@dartlang.org.
Kasper Peulen
2015-07-09 22:40:44 UTC
Permalink
Post by 'Bob Nystrom' via Dart Misc
True. But even with var, you can just Go to Definition on getVersions() and
then Go to Definition on the declared return type there. I don't think
there's a real usability win to having the return type annotated.
I think there is a win in usability. Say I want to know the type of versions
:

*Scenario 1:* It is typed, and I just read that it is List<Version>.

*Scenario 2: *It is not typed. To find out the type we need to first find
out the type of pubspecs.

- To find out the return type of pubspecs, we need to find out the
return type of source.getVersions(package, package).
So we can press F1 and see that the return type is Future<List<Pubspec>>.
Then we need to know that await Future<T> returns T.
From that we can deduce that await source.getVersions(package, package);
is of type List<Pubspec>.
And so pubspecs is of type List<Pubspec>
- Then we need to find out the return type of pubspecs.map((pubspec) =>
pubspec.version) for that we need to find out that the method map in
this casereturns Iterable<T> where T is the type of pubspec.version
If we haven't heard of the map method before that may be not even so
trivial to deduce from the docs.
So we now need to look up that pubspec.version is of of type Version and
therefore
pubspecs.map((pubspec) => pubspec.version) is of type Iterable<Version>.
- Then we need to find out the return type of
Iterable<Version>.where(constraint.allows)is Iterable<Version>
- And last step is probably the easiest, which is that Iterable<Version>
returns List<Version>

Okay I see that if the reader is familiar with the dart language and the
core libraries. One may be able to do this whole reasoning in 5 seconds or
less.
But in any case, I think it is clear that scenario 1 is much less time
consuming, which I would say is a real* usability win.*

You still have tons of subexpressions whose type isn't written out in the
Post by 'Bob Nystrom' via Dart Misc
code, so I don't think it adds much value to treat expressions that happen
to initialize local variables specially.
I do think there is a good reason to treat local variables specially. If
you introduce a variable, you will reference this variable in other lines.
It is not only useful to know the type if I want to understand the line
where pubspecs is declared.
Also in other lines, the variable pubspecs will be referenced. For example,
if I want to know the the type of versions, and I already know the type of
pubspecs, the reasoning above could be shortened.

The reader *has* those hints. They can just hover over any of these
Post by 'Bob Nystrom' via Dart Misc
function calls to see them.
What I don't think its worth doing is baking that into the source text. I
look at this as extension of the DRY
<https://en.wikipedia.org/wiki/Don't_repeat_yourself> principle. If the
type can be statically determined from the initializer, it is strictly
redundant to also spell it out in the code.
It is certainly redundant. It is redundant, but saves the reader time. You
can determine that the type of versions is List<Version>. But then,
following your reasoning, if we can determine the type, why would we even
bother giving the variable the name versions ? This is certainly redundant,
we could also just call it shortly something like v, or var1. And let the
user find out himself that this variable contains some Version's.

Of course this is silly. Giving the user hints with clear local variable
names makes the code easier to read. And in the same way, it is easier to
read the code, if this variable name has an associated type. For example,
if I read a line, somewhere else in the code where versions is mentioned.
If I cmd+hover it or F1 it, I want to see the type:

<Loading Image...>
Otherwise, I may wonder, if versions contains a List<String> with the
string representation of a version. Or whatever.
Post by 'Bob Nystrom' via Dart Misc
I think implicit downcasting is a misfeature in the language. Either way,
the analyzer could be smarter here and provide a hint.
From the comment here:
https://github.com/dart-lang/dart-pad/issues/302#issuecomment-91373539

I understood that there are no plans to chance this, and that this behavior
is by design... If I understand correctly, the idea is that factory
constructors can also return subtypes, so therefore you can not know for
sure that the type in that case would be InputElement, and not MathInput.

Can you point to a statically-typed language that came out in the past
Post by 'Bob Nystrom' via Dart Misc
decade, has a decent user base, and *doesn't* do local variable inference?
I'm an amateur. Dart is the first language I've really tried to learn, and
I haven't felt the desire to learn/study other langues yet ;)

But nevertheless, I'm not arguing that the analyser should stop doing local
variable inference at all. I think it is an extremely useful feature.

1) The less a variable is used, the less useful it is to type it. So for
lambda functions with arrow functions, I think there are many cases there
that types don't add much at all. For example [1,2,3,4].map((i) =>
i+1).toList(); I won't say adding types has much value here.

I'm not arguing using types always and everywhere.

2) If I understand correctly, the reason that the following code gives an
error, is also because of local variable inference:

int i = 1.toString()

So I think local variable inference is very useful, also if you use type
annotations.

It's not dogmatic. That's why the guideline is "PREFER", not "DO".


Well, the rule may not be dogmatic, but I see many times code, where it
feels like var is used dogmatically. Therefore I added this example:

var directories = pluralize('Directory', directoryNames.length, plural:
'Directories');
var names = toSentence(directoryNames.map((dir) => '"$dir"'));
var verb = pluralize(singularVerb, directoryNames.length, plural: pluralVerb
);

Here I don't see any reasons to use var. Especially, because String is such
a short type name. The only reason why I would think someone may prefer var above
String in this example is because there is a style guide that says that
local vars should be typed with var.

But that's because these happen to have a particularly short type name.
Post by 'Bob Nystrom' via Dart Misc
It's hard to generalize from this.
I don't think it is hard to generalize. I think you could generalize this
to the following style guide:
*"Consider adding a type annotation for a local variable, if it doesn't add
visual noise. (Especially if the variable is referenced a lot.)"*

Or something like that :)
--
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

To unsubscribe from this group and stop receiving emails from it, send an email to misc+***@dartlang.org.
'Bob Nystrom' via Dart Misc
2015-07-09 23:31:19 UTC
Permalink
But then, following your reasoning, if we can determine the type, why
would we even bother giving the variable the name versions ? This is
certainly redundant, we could also just call it shortly something like v,
or var1.
No, the name is *not* redundant with the type. This is a big part of why I
don't think local type annotations add much value. In many cases, the type
tells you very little about the actual object in question. A well-chosen
name tells you what the object *actually means*.

Consider:

String s1 = pluralize('Directory', directoryNames.length, plural:
'Directories');
String s2 = toSentence(directoryNames.map((dir) => '"$dir"'));
String s3 = pluralize(singularVerb, directoryNames.length, plural:
pluralVerb);

This is fully typed like you suggest. It's also totally unreadable. It's
the *names* that make this code clear. The types—the fact that those are
strings—doesn't really add much. If you refactored that code to use a list
of strings, or some other type, it wouldn't make that much of a difference.

As long as the names are good, the type is secondary. (And if the names
aren't good, the types won't save you.)

Of course this is silly. Giving the user hints with clear local variable
names makes the code easier to read. And in the same way, it is easier to
read the code, if this variable name has an associated type. For example,
if I read a line, somewhere else in the code where versions is mentioned.
<https://lh3.googleusercontent.com/-8izd02CtqVU/VZ70vnSyo6I/AAAAAAAAAgQ/TPIQX9uwJC4/s1600/Untitled.png>
I agree totally. We need to improve inference and our IDE tooling to get
this. We won't get that if we don't use var to push on the tools to be
smarter.
<https://lh3.googleusercontent.com/-8izd02CtqVU/VZ70vnSyo6I/AAAAAAAAAgQ/TPIQX9uwJC4/s1600/Untitled.png>
https://github.com/dart-lang/dart-pad/issues/302#issuecomment-91373539
I understood that there are no plans to chance this, and that this
behavior is by design... If I understand correctly, the idea is that
factory constructors can also return subtypes, so therefore you can not
know for sure that the type in that case would be InputElement, and not
MathInput.
Ah right. The current behavior is intended, but I think we need to push on
the language to be smarter.

We have gotten consistent feedback from users that they want more inference
and more static type safety.

1) The less a variable is used, the less useful it is to type it. So for
lambda functions with arrow functions, I think there are many cases there
that types don't add much at all. For example [1,2,3,4].map((i) =>
i+1).toList(); I won't say adding types has much value here.
Right. The smaller a variable's extent, the less useful it is to type it.
In Dart, I think most functions are small enough that even local variables
have small extent. If you compare modern code to old C code, you'll see
functions have gotten smaller and smaller over time.
2) If I understand correctly, the reason that the following code gives an
int i = 1.toString()
There's no actual inference going on here. This is just the usual type
propagation rules to determine the type of the initializer and comparing
that to the explicit type annotation of the local variable.

Well, the rule may not be dogmatic, but I see many times code, where it
'Directories');
var names = toSentence(directoryNames.map((dir) => '"$dir"'));
pluralVerb);
Here I don't see any reasons to use var.
In pub, we chose to consistently use var for all local variables. The *style
guide* isn't dogmatic about what you have to do. Any given user can choose
how they want to apply the guideline.
Especially, because String is such a short type name.
That's not an easy rule to consistently follow in a codebase. How long is
too long? If I refactor a class name to be shorter or longer, do I have to
go back and add or remove type annotations on all of the local variables of
that type?
I don't think it is hard to generalize. I think you could generalize this
*"Consider adding a type annotation for a local variable, if it doesn't
add visual noise. (Especially if the variable is referenced a lot.)"*
Or something like that :)
The style guide is already soft here. You can ignore the rule if you want.
If you do, you aren't a bad person. Santa Claus will still bring you
presents, and you can sleep easy at night. :)

Of course, I would prefer it if you adopted using "var" more because I
think it leads to more readable code that is more consistent with the rest
of the Dart ecosystem. I also think it encourages the Dart team to move in
a direction of smarter tools and more inference, and I believe firmly that
we *have* to do that in order to be a successful language.

Cheers!

- 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

To unsubscribe from this group and stop receiving emails from it, send an email to misc+***@dartlang.org.
Kasper Peulen
2015-07-10 01:38:23 UTC
Permalink
Post by 'Bob Nystrom' via Dart Misc
As long as the names are good, the type is secondary. (And if the names
aren't good, the types won't save you.)
I don't agree I think List<Version> v is easier to parse then var versions.
And especially the combination List<Version> versions.

This is a big part of why I don't think local type annotations add much
Post by 'Bob Nystrom' via Dart Misc
value. In many cases, the type tells you very little about the actual
object in question
I don't agree, sometimes it tells you almost everything you need to know.

The types—the fact that those are strings—doesn't really add much.


I can't believe you say that. If you see some variable referenced that is
called directories.Of course, having a good name is very valuable, I won't
argue with that at all. But when the variable is referenced somewhere else,
being able to easily see that this is a String and not for example a
List<Directory> type, I *do* think that this add much

Of course, I would prefer it if you adopted using "var" more because I
Post by 'Bob Nystrom' via Dart Misc
think it leads to more readable code that is more consistent with the rest
of the Dart ecosystem.
Of course, my purpose is the opposite. I hope that you adopt using types
more, and change the style guide, which would in my view make the Dart
ecosystem more readable. I see that I have little chance ;)

I believe firmly that we *have* to do that in order to be a successful
Post by 'Bob Nystrom' via Dart Misc
language.
Maybe that is because from my angle of view, I want to be productive in
dart today. I don't think you can seriously argue that if you use var
consistently *today *in Webstorm, that the code becomes more readable.

I do agree that with an improved analyser, and when hovering the variable
shows me the inferred type (or the documentation of the variable show me
that), then I would feel less need to add types for local variables.
Especially for callbacks/lambda functions, as you don't have to write var.
But if you have to write something, writing var instead of String feels
stupid to me. var means absolutely nothing. If you are going to write
something, write something meaningful. I would probably consider using final instead
of String whenever that is appropiate.

I think it leads to more readable code that is more consistent with the
Post by 'Bob Nystrom' via Dart Misc
rest of the Dart ecosystem.
In my experience, the Dart ecosystem is not consistently applying this
style guide. My first Dart project I contributed to was DartPad, which I
guess is in the Dart ecosystem, but var is used very rarely there, the rare
cases where var is used are actually coming from me I think. (I feel bad
about this of course :P)

I agree totally. We need to improve inference and our IDE tooling to get
Post by 'Bob Nystrom' via Dart Misc
this. We won't get that if we don't use var to push on the tools to be
smarter.
Haha, this is maybe an unexpected coincidence. One of the first features
that I introduced to DartPad was live documentation whenever you click on a
dart element in the code. Although I don't use var often myself, I did add
inferred types to the documentation (in contrast to Webstorm...)

<Loading Image...>
That should prove that I care about inferred types ! And that you can care
about improving tooling for inferred types even if you rarely use var
yourself.

I do agree that improving the inference of the analyser should be top
priority, and that Webstorm should improve their inferred type support.
I just don't agree that using var *today* in local variables makes dart
code more readable, but I guess we are not going to agree about this :)
--
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

To unsubscribe from this group and stop receiving emails from it, send an email to misc+***@dartlang.org.
Don Olmstead
2015-07-10 01:21:23 UTC
Permalink
Since no one has mentioned it a good workaround for the analyzer puking on
whats going on is to do a cast.

var canvas = querySelector('canvas') as CanvasElement;

Then you're keeping the var and you get what you want. Technically its more
typing but visually I like it better since var's tend to be grouped
together.
--
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

To unsubscribe from this group and stop receiving emails from it, send an email to misc+***@dartlang.org.
Loading...