How does that address my question? I didn't suggest the
replacement or removal of syntax.

I think your suggestion is not so useful because in many cases
you don't want to use "auto". To justify the introduction of a
new syntax it needs to cover many usage cases, or to do something
that before was impossible/hard to, or bug prone, or very long to
write, or very inelegant, etc.
With other people I have suggested to introduce a syntax like:
int[$] array = [1, 2, ....many more....];
This is useful because counting the items manually is boring and
bug-prone.
Bye,
bearophile

It is a terse way of assigning and initializing an automatically
typed variable, helping meld what I understand one of D's aims to
be that of the power of a C/C++ language with some of the
syntactic elegance of languages like Python. In broad terms D and
Go would seem to outline the general direction of C/C++ ideas, it
would seem like a good idea to use the good ideas of each to move
toward the optimum language.

Is there any reason not to add this so you can use foo := bar as
a shorthand for auto foo = bar?

Any proposed feature must have a solid use case and reason for being in the
language. It needs to add real value. If you want a feature in the language,
you need to show why it's truly worth having. This is especially true at this
stage in the game. The language is supposed to be essentially stable at this
point. We're ironing some stuff out still (primarily due to the compiler being
behind the language definition), but we're not looking to make changes without
good reason. And breaking changes _really_ need a good reason.
As for your particular suggestion, I don't see how it adds anything but
complication. So, you write
foo := bar;
instead of
auto foo = bar
_All_ it is is a syntactic change. It saves you a few characters. It adds _no_
new functionality. It just adds one more thing that someone learning D has to
learn and know. And it's not at all in line with how variable declarations
normally work. What we currently have is very consistent. := doesn't fit in
with that at all. For all variable declarations, we have
Type name = initializer;
In some cases, the type is inferred, but then type specifier is used in its
place:
auto name = initializer;
const name = initializer;
immutable name = initializer;
shared name = initializer;
enum name = initializer;
If we implemnted your suggestion, then we'd have
name := initializer;
auto name = initializer;
const name = initializer;
immutable name = initializer;
shared name = initializer;
enum name = initializer;
It _only_ covers the auto case, and it doesn't fit in with the rest at all.
Not to mention, there are some programming languages (e.g. Pascal) which use
:= for normal assignment, so it would be confusing for anyone familiar with
those languages. I'm not aware of any language which specifically uses := for
auto, just for assignment (though if the language doesn't require variable
declarations, then all assignments are essentially the same as declarations
with auto). So, what you're proposing (AFAIK) would be a new usage for :=,
even if it's similar to what other languages have done.
If you want something like this added, you need a compelling use case, and you
don't seem to have one.
- Jonathan M Davis

Is there any reason not to add this so you can use foo := bar
as
a shorthand for auto foo = bar?

Any proposed feature must have a solid use case and reason for
being in the
language. It needs to add real value. If you want a feature in
the language,
you need to show why it's truly worth having. This is
especially true at this
stage in the game. The language is supposed to be essentially
stable at this
point. We're ironing some stuff out still (primarily due to the
compiler being
behind the language definition), but we're not looking to make
changes without
good reason. And breaking changes _really_ need a good reason.
As for your particular suggestion, I don't see how it adds
anything but
complication. So, you write
foo := bar;
instead of
auto foo = bar
_All_ it is is a syntactic change. It saves you a few
characters. It adds _no_
new functionality. It just adds one more thing that someone
learning D has to
learn and know. And it's not at all in line with how variable
declarations
normally work. What we currently have is very consistent. :=
doesn't fit in
with that at all. For all variable declarations, we have
Type name = initializer;
In some cases, the type is inferred, but then type specifier is
used in its
place:
auto name = initializer;
const name = initializer;
immutable name = initializer;
shared name = initializer;
enum name = initializer;
If we implemnted your suggestion, then we'd have
name := initializer;
auto name = initializer;
const name = initializer;
immutable name = initializer;
shared name = initializer;
enum name = initializer;
It _only_ covers the auto case, and it doesn't fit in with the
rest at all.
Not to mention, there are some programming languages (e.g.
Pascal) which use
:= for normal assignment, so it would be confusing for anyone
familiar with
those languages. I'm not aware of any language which
specifically uses := for
auto, just for assignment (though if the language doesn't
require variable
declarations, then all assignments are essentially the same as
declarations
with auto). So, what you're proposing (AFAIK) would be a new
usage for :=,
even if it's similar to what other languages have done.
If you want something like this added, you need a compelling
use case, and you
don't seem to have one.
- Jonathan M Davis

It's from Go, which has proper tuple syntax, it's main use is
that it allows
you to declare a new var and reuse an old one. So it would be
worth looking in to when we introduce a proper tuple syntax, but
not now.

Unlike regular variable declarations, a short variable
declaration may
redeclare variables provided they were originally declared in
the same block
with the same type, and at least one of the non-blank variables
is new. As a
consequence, redeclaration can only appear in a multi-variable
short
declaration. Redeclaration does not introduce a new variable; it
just assigns
a new value to the original.

I see that this is not going to happen for D2 but as a debate for
a future D3 (and please just ignore my post if you find this in
some way exasperating, I am interested but do not mean to cause
friction):
Just as a question about the existing syntax as you listed
combinations to learn as a negative:

After the first aren't these all just short hand for "const auto
name = init" etc with the given keyword? If your argument is that
additional cases are bad then this is a case for what appears to
be syntactic reasons. It feels as if initialization should be
more explicit than keyword varname. As a beginner I certainly
found that odder than :=.
Syntax confusion with other languages is not a strong argument,
well at least as the confusion is with unrelated languages.
Fortran uses /= for not equal, Matlab uses ~=, while that is D's
append to self.
Terse elegance is important in making languages quick to take in
and work with, it's not an argument of new function but that is
not the only reason to include features, convenience is a good
reason when there is no ambiguity.

I see that this is not going to happen for D2 but as a debate for
a future D3 (and please just ignore my post if you find this in
some way exasperating, I am interested but do not mean to cause
friction):
Just as a question about the existing syntax as you listed
combinations to learn as a negative:

After the first aren't these all just short hand for "const auto
name = init" etc with the given keyword? If your argument is that
additional cases are bad then this is a case for what appears to
be syntactic reasons. It feels as if initialization should be
more explicit than keyword varname. As a beginner I certainly
found that odder than :=.
Syntax confusion with other languages is not a strong argument,
well at least as the confusion is with unrelated languages.
Fortran uses /= for not equal, Matlab uses ~=, while that is D's
append to self.
Terse elegance is important in making languages quick to take in
and work with, it's not an argument of new function but that is
not the only reason to include features, convenience is a good
reason when there is no ambiguity.

A language can certainly use whatever syntax it wants to, but if it uses a
syntax that no other language uses or reuses a particular piece of syntax for
something completely different, it comes at a cost in terms learning and
knowing the language. It's often the case that someone will argue that
something should be added simply because another language does something in a
particular way, and use that as an argument. Arguing that something shouldn't
be added because no other language does it that way is basically the same
argument but in reverse.
D _has_ done some if its own stuff already (e.g. ~ and ~= for concatenation and
appending), so the fact that no other language did something a particular way
is not necessarily a barrier to having D do it that way, but there needs to be
a good reason for it, and at this stage in the game, we're not gonig to make
changes like that without a _really_ good reason.
Regardless, := just doesn't match what D currently does. And given that other
languages have
auto name = initializer;
or something very similar (e.g. IIRC C# uses var instead of auto; C++11
however uses the exact same syntax as D), auto is very much in line with what
other languages are doing (regardless of whether any other language uses := in
a manner similar to what you're proposing). So, whether auto or := is more
immediately obvious is completely a matter of what your personal experience
is. It's going to vary from programmer to programmer. Personally, if a
language uses :=, I would have expected it to be used for what D uses = for
rather than auto.
Obviously, you're going to have to learn new stuff in learning any language,
and we're unlikely to change anything at this point simply because someone
thinks that another language's syntax is better and that D should use it. Even
if the other syntax _were_ better, it's too late in the game to change it now
without a really compelling reason. And adding a second way to do things on
top of the first is just going to make it so that there are _more_ things for a
D newbie to learn, and D is already far from being small.
Who knows what'll happen with D3. It's years off yet, if it will even ever
happen at all. What we do with it will be discussed then, so it's pretty much
irrelevant now. However, I'd be very surprised if we made a minor syntactic
change like this for it, since it would just make D2 code harder to port to D3
without providing any real benefit (the only benefit is whatever aesthetic
benefit a particular programmer might see in using := over auto).
You're free to propose and discuss possible changes for D3, but there's very
little
in terms of language changes that are going to happen to D2 at this point
(especially syntactically), and personally, I think that it's a waste of time to
discuss possible changes for D3 given that it's likely 10+ years off and that
what
we decide to do with it is going to be highly dependent on the lessons learned
while using D2 over that time period.
- Jonathan M Davis

After the first aren't these all just short hand for "const
auto name = init" etc with the given keyword?

No. Many don't realise this, but "auto" doesn't actually stand
for "automatic type inference". It is a storage class, like
static, extern, etc., and it means that the variable stops
existing at the end of the scope. It is, however, the default
storage class, which is why it is useful when all you want is
type inference. Even C has auto.
Lars

No. Many don't realize this, but "auto" doesn't actually stand
for "automatic type inference". It is a storage class, like
static, extern, etc., and it means that the variable stops
existing at the end of the scope. It is, however, the default
storage class, which is why it is useful when all you want is
type inference. Even C has auto.

No. Many don't realise this, but "auto" doesn't actually stand
for "automatic type inference". It is a storage class
Lars

auto int a = 5;
// Error: variable a storage class 'auto' has no effect if type
is not inferred, did you mean 'scope'?
I don't understand what kind of a "storage class" this is.
You would be correct in C, but is it really a 'storage class' in
D?
(Sure it's called that, but it doesn't seem to behave like one...)

No. Many don't realise this, but "auto" doesn't =C2=A0actually stand for
"automatic type inference". It is a storage class
Lars

auto int a =3D 5;
// Error: variable a storage class 'auto' has no effect if type is not
inferred, did you mean 'scope'?
I don't understand what kind of a "storage class" this is.
You would be correct in C, but is it really a 'storage class' in D?
(Sure it's called that, but it doesn't seem to behave like one...)

The word 'storage class' seems to me that comes from C language, but I
think it is almost incorrect word in current D.
Different from C, it can qualify almost of D declarations - variable,
function, template, and class/struct declarations.
I think that to invent new/better word for that element of the
language is important work of the community.
Kenji Hara

After the first aren't these all just short hand for "const
auto name = init" etc with the given keyword?

No. Many don't realise this, but "auto" doesn't actually stand
for "automatic type inference". It is a storage class, like
static, extern, etc., and it means that the variable stops
existing at the end of the scope. It is, however, the default
storage class, which is why it is useful when all you want is
type inference. Even C has auto.

auto is called a storage class, but where did you read that auto would
make the variable stop existing at the end of the scope ?
int delegate(int) add(int i, int j)
{
auto k = i+j;
return a => a+k;
}
Are you sure k will stop existing at the end of the scope ? I have no
compiler at hand to check this, but I would be very surprised.
Object Create()
{
auto k = new Object();
return k;
}
Same question.
--
Christophe

After the first aren't these all just short hand for "const
auto name = init" etc with the given keyword?

No. Many don't realise this, but "auto" doesn't actually stand
for "automatic type inference". It is a storage class, like
static, extern, etc., and it means that the variable stops
existing at the end of the scope. It is, however, the default
storage class, which is why it is useful when all you want is
type inference. Even C has auto.

auto is called a storage class, but where did you read that auto would
make the variable stop existing at the end of the scope ?

Yeah. I'm pretty darn sure that he's wrong on that. All auto is type
inference. auto has no effect on the lifetime of a variable. _All_ variables
cease to exist when they exit scope. And reference and pointer types continue
to exist on the heap (it's just that the pointer or reference is gone) without
being destroyed or freed or whatnot. So, I don't know where Lars got the idea
that auto was anything other than type inference. Sure, it might be termed a
storage class, but that term seems to be pretty much meaningless in D.
- Jonathan M Davis

After the first aren't these all just short hand for "const
auto name = init" etc with the given keyword?

No. Many don't realise this, but "auto" doesn't actually
stand
for "automatic type inference". It is a storage class, like
static, extern, etc., and it means that the variable stops
existing at the end of the scope. It is, however, the default
storage class, which is why it is useful when all you want is
type inference. Even C has auto.

auto is called a storage class, but where did you read that
auto would
make the variable stop existing at the end of the scope ?

Yeah. I'm pretty darn sure that he's wrong on that. All auto is
type
inference. auto has no effect on the lifetime of a variable.
_All_ variables
cease to exist when they exit scope. And reference and pointer
types continue
to exist on the heap (it's just that the pointer or reference
is gone) without
being destroyed or freed or whatnot. So, I don't know where
Lars got the idea
that auto was anything other than type inference. Sure, it
might be termed a
storage class, but that term seems to be pretty much
meaningless in D.
- Jonathan M Davis

After the first aren't these all just short hand for "const
auto name = init" etc with the given keyword?

No. Many don't realise this, but "auto" doesn't actually
stand
for "automatic type inference". It is a storage class, like
static, extern, etc., and it means that the variable stops
existing at the end of the scope. It is, however, the default
storage class, which is why it is useful when all you want is
type inference. Even C has auto.

auto is called a storage class, but where did you read that
auto would
make the variable stop existing at the end of the scope ?

Yeah. I'm pretty darn sure that he's wrong on that. All auto is
type
inference. auto has no effect on the lifetime of a variable.

I admit that "stop existing at the end of the scope" was perhaps
imprecise to the point of being wrong. Here's Microsoft's
description of the auto storage class in C:
The auto storage-class specifier declares an
automatic variable, a variable with a local
lifetime. An auto variable is visible only in
the block in which it is declared.
All variables except those marked 'register', 'static' or
'extern' are 'auto' in C.
That said, I was still wrong. :) I just tried it now, and
apparently you can write pointless stuff like "auto extern int
foo;" and DMD will compile it just fine. (And, unless that is a
bug, it means D has redefined 'auto' to mean absolutely nothing,
except to be a marker saying "this is a declaration", allowing
one to omit both storage class and type.)
auto should probably be removed from the list of storage classes
in the D spec, then.

_All_ variables
cease to exist when they exit scope.

Not static ones, but again maybe you took "stop existing" to
refer to the name rather than the storage.
-Lars

That said, I was still wrong. :) I just tried it now, and
apparently you can write pointless stuff like "auto extern int
foo;" and DMD will compile it just fine. (And, unless that is a
bug, it means D has redefined 'auto' to mean absolutely nothing,
except to be a marker saying "this is a declaration", allowing
one to omit both storage class and type.)

dlang.org states:
| Auto Attribute
| The auto attribute is used when there are no other attributes and type
| inference is desired.
So indeed, in a variable declaration, auto has no meaning other than
saying "this is a declaration".
--
Christophe

That said, I was still wrong. :) I just tried it now, and
apparently you can write pointless stuff like "auto extern int
foo;" and DMD will compile it just fine. (And, unless that is a
bug, it means D has redefined 'auto' to mean absolutely nothing,
except to be a marker saying "this is a declaration", allowing
one to omit both storage class and type.)

I believe that auto has been redefined in C++11 as well. In both, all it really
means is that the type is inferred.

auto should probably be removed from the list of storage classes
in the D spec, then.

That said, I was still wrong. :) I just tried it now, and
apparently you can write pointless stuff like "auto extern int
foo;" and DMD will compile it just fine. (And, unless that is
a
bug, it means D has redefined 'auto' to mean absolutely
nothing,
except to be a marker saying "this is a declaration", allowing
one to omit both storage class and type.)

I believe that auto has been redefined in C++11 as well. In
both, all it really
means is that the type is inferred.

The history of 'auto' in C++ is actually a bit interesting.
Here's a bit from Bjarne Stroustrup's C++11 FAQ (which is an
awesome resource, btw):
"The auto feature has the distinction to be the earliest to be
suggested and implemented: I had it working in my Cfront
implementation in early 1984, but was forced to take it out
because of C compatibility problems. Those compatibility problems
disappeared when C++98 and C99 accepted the removal of "implicit
int"; that is, both languages require every variable and function
to be defined with an explicit type. The old meaning of auto
("this is a local variable") is now illegal. Several committee
members trawled through millions of lines of code finding only a
handful of uses -- and most of those were in test suites or
appeared to be bugs."

auto should probably be removed from the list of storage
classes
in the D spec, then.

The spec isn't _at all_ clear on what on earth a storage class
is in D. I
tried to get clarification on that not too long ago and failed.

At the very least, if we keep using that term, it should have
something to do with how stuff is stored. ;)
-Lars

I believe that auto has been redefined in C++11 as well. In
both, all it really
means is that the type is inferred.

That's what I seemed to remember as well. Originally it had
something to do with scope, but it was basically obsolete because
that was the default storage class anyway, so nobody was using it.
In the latest iteration of C++ they decided to redefine the
keyword to mean automatic type inference. This avoided having to
introduce a new keyword (which could break existing code that
happened to use that word for a variable name) and it was
unlikely to cause problems with old code. Storage class for local
variables is still the same default anyway.
(The only possible error could be if someone wrote "auto a = b"
as shorthand for "auto int a = b" with b some type other than
int, which would have been legal in very old versions of C but
extremely unlikely to ever be used since auto does nothing for an
int)

I believe that auto has been redefined in C++11 as well. In
both, all it really
means is that the type is inferred.

That's what I seemed to remember as well. Originally it had
something to do with scope, but it was basically obsolete because
that was the default anyway, so nobody was using it.
In the latest iteration of C++ they decided to redefine the
keyword to mean automatic type inference. This avoided having to
introduce a new keyword (which could break existing code that
happened to use that word for a variable name) and it was
unlikely to cause problems with old code. Storage class for local
variables is still the same default anyway so any code that relied
on variables being old-style "auto" would still work the same.
The only possible error could be if someone wrote "auto a = b"
as shorthand for "auto int a = b" with b some type other than
int, which would have been legal in very old versions of C but
extremely unlikely to ever be used since auto does nothing for an
int. They decided to take that chance :-)

Back in the ancient history of D (y'know, several years ago)
there actually was an 'auto' storage class as described here, and
it was the default as with C. It is retained in the current
usage so that type inference for undecorated locals would still
be available, but indeed no longer serves any other purpose.
Lars is still right in the sense that 'const a = b' really isn't
shorthand for 'const auto a = b'. However, it's largely moot
since the original meaning of auto is gone. Indeed "storage
class" in general seems to have gotten out of hand, as a term.
It would be easy enough to clean up by moving the inappropriate
members out of that list and into a new yet-to-be-named category.
Of course I suppose the compiler's internals would be free to
continue seeing them all as one happy family as it now does.
----------
More on topic, the moment I saw the mention of := it immediately
read as "Pascal like assignment" to me. I have no problem with
languages that actually treat this as two operators (: type =
init) with the digraph as the type inference shorthand, but
outside those sort of grammars it just feels "out of place." The
only place this pattern appears in D is in template parameters,
and even that has always looked a little funky to me (although
not so bad as to be abhorrent).
template Foo ( T : ulong = size_t ) { ... }
// accepts any unsigned integral type, and defaults to the size_t
alias

Not to mention, there are some programming languages (e.g.
Pascal) which use := for normal assignment, so it would be
confusing for anyone familiar with those languages.

AutoIt or AutoHotKeys is one, where = and := do two very
different things (and confusing for a first time user).
As for the topic of discussion, I think := should not be used as
it has very few useful cases, but also it's making two
incompatible operators compatible.
Consider:
test:=5;
for(/*something*/) {
/*something*/
b++;
if (b > 10)
goto test;
}
--
In the example above, test:=5 should have been test: b=5. It may
potentially hide even worse bugs, where currently := is illegal
and easy to spot by a compiler error.
Besides, isn't 'auto' short enough? as mentioned you may save 2
characters. Not worth it. Be worse if you use it in two places
and it's now trying to declare the same variable twice and
there's nothing there suggesting it's being declared. One
character is easy to miss or forget.
The worst bugs I've gone against are usually the simplest,
easiest and most subtle.

Is there any reason not to add this so you can use foo := bar
as a shorthand for auto foo = bar?

I would be against this change. There isn't much to say agaist it
especially since => was fairly recently added (though has more
benefit than I see here). The word auto is not hard to type for a
Dvorak user, it kind of just roles off (auto). Declarations would
then need to be identified by starting with auto or variable :=.
And on that similar point, Vim fails to go to declarations
already. While I don't anticipate trying to fix this anytime
soon, the new form would likely make this yet another thing to go
wrong.
Somewhere you made a comment about
const auto ...;
No, it is
const int ...;
You can't include auto if you are using const/immutable... but
you can include the actual type.

Is there any reason not to add this so you can use foo := bar
as a shorthand for auto foo = bar?

If the rest of D's syntax where completely different, then I
would agree with you're purposed syntax here. But as it stands,
this is completely inconsistent with the rest of D, and for that
reason alone shouldn't be introduced. All it can add is confusion.
This is one of the many things I really don't like about Go.
Often in Go you'll get syntax like:
var x int
y := 30
which just looks like there's completely different things going
on between those lines. What would have been much better is to
simply remove the 'var' keyword altogether:
x : int
y := 10
// synonymous:
z := 10u
z : uint = 10