I've got some ideas about how to make the const syntax more
consistent.
First I will show you the current situation.
Then I will list the confusions and possible solutions.
Some days ago I already mentioned my first idea on IRC, but got no replies.
Also I know that you, Walter, hardly don't change features, which
already have been implemented.
And my suggestions would require this of course.
The "define proposal" is not such a big change in the language,
in opposite to the much more important idea about
"putting the return type in a bracket at the end".
Because this is what the last idea requires, it's written after "WAIT:".
Nevertheless I will give it a try, because 2.0 is still alpha and it
will break code compatibility anyway.
currently the keyword const(/invariant) has three meanings:
-----------------------------------------------------------
1. alone: const x = 1; compile-time variable (not an lvalue)
2. with(): const(P) p = new Point(1,2); run-time object, which is
protected from changes
3. alone: const P func(P p) { writefln(p.x, " ", p.y); }; attribute for
a member function: the function can't change any class fields
confusions and solutions:
-------------------------
#1
1. const x = 1;
2. const(P) p = new Point(1,2);
you see const first and later recognize the brackets
one would not expect brackets to lead to a completely different meaning
of the forrun keyword
1. define x = 1;
2. const(P) p = new Point(1,2);
can't be confused anymore, different keywords
define defines a compile-time variable
const / invariant has nothing to do with compile-time anymore. it only
means protection
#2
3. const P func(P p) { ... }
reads like: func returns a const(P)
const / invariant alone (without brackets) is an attribute and has no
other meaning
further proposal: returned types in a bracket at the end:
3. const func (P p) (P) { ... }
//templated syntax: const func!(T) (T p) (T) { ... }
#3
1. same meaning: invariant x = 1; const x = 1;
not allowed anymore: const(/invariant) alone is an attribute, instead use:
1. define x = 1;
#4
//this is ok: final int x = 1; const(int)* xptr = &x; // but:
2. const(int) x = 1;
this is nonsense and also atm it could be confused with:
1. const int x = 1;
the compiler should issue at least a warning, and instead you should use:
1. define x = 1;
#5
void func(const P p) { typeof(p) == const(P) }
bad, because one could expect this to be also valid then:
const P p = new P(1,2); //but fails of course
correctly is has to be:
void func(const(P) p) { ... }
void func(ref const(P) p) { p = new P(3,4); } //OK
//void func(const(int) i) { ... } //const(int) nonsense (see #4)
//void func(ref const(int) i) { ... } //const(int) nonsense (see #4)
compiler should issue an error
const(/invariant) alone is an attribute
WAIT:
-----
because we have another syntax for compile-time variables now,
we could say that:
const P** ptr2ptr2P means:
const(P**) ptr2ptr2P
in this case, #5 would be allowed
but this would also require #2 further proposal to be implemented,
because if it wasn't:
const P** func() { ... }
would not only be confused with, but it would be THE SAME as:
const(P**) func() { ... }
then the correct form would have to be:
const func() (const P**) { ...}
note that #4 would be true for: const int x = 1; then
this would be nonsense, because it would be the same as: const(int) x = 1;
so the compiler should issue at least a warning
PS: Having the return types in a bracket at the end, would make it
possible to implement multiple return values / return tuples
in a consistent way, too.
It would also allow more tricks, like returning local values of a
function, avoiding ref, etc etc ...
I would really enjoy to get some replies (especially yours, Walter),
even if it's just a: "No that's totally stupid" ;)
Best regards,
Daniel

I've got some ideas about how to make the const syntax more
consistent.
First I will show you the current situation.
Then I will list the confusions and possible solutions.
Some days ago I already mentioned my first idea on IRC, but got no replies.
Also I know that you, Walter, hardly don't change features, which
already have been implemented.
And my suggestions would require this of course.
The "define proposal" is not such a big change in the language,
in opposite to the much more important idea about
"putting the return type in a bracket at the end".
Because this is what the last idea requires, it's written after "WAIT:".
Nevertheless I will give it a try, because 2.0 is still alpha and it
will break code compatibility anyway.
currently the keyword const(/invariant) has three meanings:
-----------------------------------------------------------
1. alone: const x = 1; compile-time variable (not an lvalue)

Well technically if that was what I wanted, I'd use one of 'invariant x
= 1;' or a more explicit 'final invariant(int) x = 1;'.

#3 is an issue, in my book. Not a massive one, but its there. We'll
get into that one below.

confusions and solutions:
-------------------------
#1
1. const x = 1;
2. const(P) p = new Point(1,2);
you see const first and later recognize the brackets
one would not expect brackets to lead to a completely different meaning
of the forrun keyword

My eyes are trained to spot them... still yes, a sudden shift in meaning
can be counter-intuitive. Although its not entirely a shift... you
could probably think of 'const x = 1;' as shorthand for 'final
const(int) x = 1;'.

Uhm. Ew. No, seriously, I just could not possibly handle that; I would
keep thinking I saw templates where there aren't any. Worse yet, for a
long time I'll see the '!(' and keep wondering how I could be
instantiating a template in that position, when its really a template
declaration. T'is a naughty naughty thing to mix the two -- would give
both the compiler and the user headaches. IMHO, its the
'const'/'invariant' keyword on methods that needs to move -- not sure
where it should go, though. What looks best down here? ;) (First
listing is the current state, for reference.)
const P vunc (P p) { ... }
P const func (P p) { ... }
P const:func (P p) { ... }
P const(func) (P p) { ... }
P func const (P p) { ... }
P func:const (P p) { ... }
P func (P p) const { ... }

#3
1. same meaning: invariant x = 1; const x = 1;

For basic types, there often isn't much difference anyhow. Except that
invariant members of structures allocate no memory in the structure, for
example.

not allowed anymore: const(/invariant) alone is an attribute, instead use:
1. define x = 1;
#4
//this is ok: final int x = 1; const(int)* xptr = &x; // but:
2. const(int) x = 1;
this is nonsense and also atm it could be confused with:
1. const int x = 1;
the compiler should issue at least a warning, and instead you should use:
1. define x = 1;
#5
void func(const P p) { typeof(p) == const(P) }
bad, because one could expect this to be also valid then:
const P p = new P(1,2); //but fails of course
correctly is has to be:
void func(const(P) p) { ... }
void func(ref const(P) p) { p = new P(3,4); } //OK
//void func(const(int) i) { ... } //const(int) nonsense (see #4)
//void func(ref const(int) i) { ... } //const(int) nonsense (see #4)
compiler should issue an error
const(/invariant) alone is an attribute
WAIT:
-----
because we have another syntax for compile-time variables now,
we could say that:
const P** ptr2ptr2P means:
const(P**) ptr2ptr2P
in this case, #5 would be allowed
but this would also require #2 further proposal to be implemented,
because if it wasn't:
const P** func() { ... }
would not only be confused with, but it would be THE SAME as:
const(P**) func() { ... }
then the correct form would have to be:
const func() (const P**) { ...}
note that #4 would be true for: const int x = 1; then
this would be nonsense, because it would be the same as: const(int) x = 1;
so the compiler should issue at least a warning
PS: Having the return types in a bracket at the end, would make it
possible to implement multiple return values / return tuples
in a consistent way, too.
It would also allow more tricks, like returning local values of a
function, avoiding ref, etc etc ...
I would really enjoy to get some replies (especially yours, Walter),
even if it's just a: "No that's totally stupid" ;)
Best regards,
Daniel

No that's totally stupid.
Ahh I'm just kidding. At least you're thinking about the situation and
offering suggestions. (And welcome to the tiny militia of 'const R
func()' syntax detractors. ;)) The final/const/invariant system needs
some good hammering yet -- although its off to a lovely start, danke Walter.
-- Chris Nicholson-Sauls

Uhm. Ew. No, seriously, I just could not possibly handle that; I would
keep thinking I saw templates where there aren't any. Worse yet, for a
long time I'll see the '!(' and keep wondering how I could be
instantiating a template in that position, when its really a template
declaration. T'is a naughty naughty thing to mix the two -- would give
both the compiler and the user headaches. IMHO, its the
'const'/'invariant' keyword on methods that needs to move -- not sure
where it should go, though. What looks best down here? ;) (First
listing is the current state, for reference.)
const P vunc (P p) { ... }
P const func (P p) { ... }
P const:func (P p) { ... }
P const(func) (P p) { ... }
P func const (P p) { ... }
P func:const (P p) { ... }
P func (P p) const { ... }

Definitely the last one. It's immediately familiar to anyone with a C++
background, which I guess most of those coming to D has, and which I think
are the people Walter is especially targetting. It also has the added bonus
of not complicating method declaration grammar too much.
Same list, this time a const func returning a const return value:
const const(P) func (P p)
const(P) const func (P p)
const(P) const(func) (P p)
const(P) func const (P p)
const(P) func:const (P p)
const(P) func (P p) const
I definitely prefer the last one as the cleanest of these.

Uhm. Ew. No, seriously, I just could not possibly handle that; I
would keep thinking I saw templates where there aren't any. Worse
yet, for a long time I'll see the '!(' and keep wondering how I could
be instantiating a template in that position, when its really a
template declaration. T'is a naughty naughty thing to mix the two --
would give both the compiler and the user headaches. IMHO, its the
'const'/'invariant' keyword on methods that needs to move -- not sure
where it should go, though. What looks best down here? ;) (First
listing is the current state, for reference.)
const P vunc (P p) { ... }
P const func (P p) { ... }
P const:func (P p) { ... }
P const(func) (P p) { ... }
P func const (P p) { ... }
P func:const (P p) { ... }
P func (P p) const { ... }

Definitely the last one. It's immediately familiar to anyone with a C++
background, which I guess most of those coming to D has, and which I
think are the people Walter is especially targetting. It also has the
added bonus of not complicating method declaration grammar too much.
Same list, this time a const func returning a const return value:
const const(P) func (P p)
const(P) const func (P p)
const(P) const(func) (P p)
const(P) func const (P p)
const(P) func:const (P p)
const(P) func (P p) const
I definitely prefer the last one as the cleanest of these.

Just chiming in on a slightly different note... the line that stuck out
in both examples for me was actually the const(func) line. That seems
really intuitive and consistent with the const syntax elsewhere.
I do find the const-on-the-end readable too, but really mostly because
of familiarity with C++ ;)

Uhm. Ew. No, seriously, I just could not possibly handle that; I
would keep thinking I saw templates where there aren't any. Worse
yet, for a long time I'll see the '!(' and keep wondering how I could
be instantiating a template in that position, when its really a
template declaration. T'is a naughty naughty thing to mix the two --
would give both the compiler and the user headaches. IMHO, its the
'const'/'invariant' keyword on methods that needs to move -- not sure
where it should go, though. What looks best down here? ;) (First
listing is the current state, for reference.)
const P vunc (P p) { ... }
P const func (P p) { ... }
P const:func (P p) { ... }
P const(func) (P p) { ... }
P func const (P p) { ... }
P func:const (P p) { ... }
P func (P p) const { ... }

Definitely the last one. It's immediately familiar to anyone with a
C++ background, which I guess most of those coming to D has, and which
I think are the people Walter is especially targetting. It also has
the added bonus of not complicating method declaration grammar too much.
Same list, this time a const func returning a const return value:
const const(P) func (P p)
const(P) const func (P p)
const(P) const(func) (P p)
const(P) func const (P p)
const(P) func:const (P p)
const(P) func (P p) const
I definitely prefer the last one as the cleanest of these.

Just chiming in on a slightly different note... the line that stuck out
in both examples for me was actually the const(func) line. That seems
really intuitive and consistent with the const syntax elsewhere.
I do find the const-on-the-end readable too, but really mostly because
of familiarity with C++ ;)

Although the idea is nice, I tried it out, and I don't like the look of it:
int const(getFoo)() { return foo; }
My main objection is that the const() is around getFoo, so you're saying
that the function won't change -- but how can it, it's static data. What
you really mean when you are saying it's a const function is that the
this object is constant. So how about that?
const(this) int getFoo() { return foo; }
(It's syntactically unambiguous because this is a keyword)
-- Reiner

Uhm. Ew. No, seriously, I just could not possibly handle that; I
would keep thinking I saw templates where there aren't any. Worse
yet, for a long time I'll see the '!(' and keep wondering how I
could be instantiating a template in that position, when its really
a template declaration. T'is a naughty naughty thing to mix the two
-- would give both the compiler and the user headaches. IMHO, its
the 'const'/'invariant' keyword on methods that needs to move -- not
sure where it should go, though. What looks best down here? ;)
(First listing is the current state, for reference.)
const P vunc (P p) { ... }
P const func (P p) { ... }
P const:func (P p) { ... }
P const(func) (P p) { ... }
P func const (P p) { ... }
P func:const (P p) { ... }
P func (P p) const { ... }

Definitely the last one. It's immediately familiar to anyone with a
C++ background, which I guess most of those coming to D has, and
which I think are the people Walter is especially targetting. It also
has the added bonus of not complicating method declaration grammar
too much.
Same list, this time a const func returning a const return value:
const const(P) func (P p)
const(P) const func (P p)
const(P) const(func) (P p)
const(P) func const (P p)
const(P) func:const (P p)
const(P) func (P p) const
I definitely prefer the last one as the cleanest of these.

Just chiming in on a slightly different note... the line that stuck
out in both examples for me was actually the const(func) line. That
seems really intuitive and consistent with the const syntax elsewhere.
I do find the const-on-the-end readable too, but really mostly because
of familiarity with C++ ;)

Although the idea is nice, I tried it out, and I don't like the look of it:
int const(getFoo)() { return foo; }
My main objection is that the const() is around getFoo, so you're saying
that the function won't change -- but how can it, it's static data. What
you really mean when you are saying it's a const function is that the
this object is constant. So how about that?
const(this) int getFoo() { return foo; }
(It's syntactically unambiguous because this is a keyword)
-- Reiner

Yeah, I guess there are a lot of tradeoffs with each syntax. I was
wondering what the function pointers would look like as well...
const int function() p; // Current
const(this) int function() p; // Could be confusing in a member function
int const(function)() p; // Looks like a const function pointer
int function() const p; // C++ style
And combinations...
const(const const(int) function(const(int))) p;
const(const(this) const(int) function(const(int))) p;
const(const(int) const(function)(const(int))) p;
const(const(int) function(const(int)) const) p;
But the latter isn't really valid material for comparison. Anyways, I
think the bikeshed should be orange! ;)

Uhm. Ew. No, seriously, I just could not possibly handle that; I
would keep thinking I saw templates where there aren't any. Worse
yet, for a long time I'll see the '!(' and keep wondering how I
could be instantiating a template in that position, when its really
a template declaration. T'is a naughty naughty thing to mix the
two -- would give both the compiler and the user headaches. IMHO,
its the 'const'/'invariant' keyword on methods that needs to move
-- not sure where it should go, though. What looks best down
here? ;) (First listing is the current state, for reference.)
const P vunc (P p) { ... }
P const func (P p) { ... }
P const:func (P p) { ... }
P const(func) (P p) { ... }
P func const (P p) { ... }
P func:const (P p) { ... }
P func (P p) const { ... }

Definitely the last one. It's immediately familiar to anyone with a
C++ background, which I guess most of those coming to D has, and
which I think are the people Walter is especially targetting. It
also has the added bonus of not complicating method declaration
grammar too much.
Same list, this time a const func returning a const return value:
const const(P) func (P p)
const(P) const func (P p)
const(P) const(func) (P p)
const(P) func const (P p)
const(P) func:const (P p)
const(P) func (P p) const
I definitely prefer the last one as the cleanest of these.

Just chiming in on a slightly different note... the line that stuck
out in both examples for me was actually the const(func) line. That
seems really intuitive and consistent with the const syntax elsewhere.
I do find the const-on-the-end readable too, but really mostly
because of familiarity with C++ ;)

Although the idea is nice, I tried it out, and I don't like the look
of it:
int const(getFoo)() { return foo; }
My main objection is that the const() is around getFoo, so you're
saying that the function won't change -- but how can it, it's static
data. What you really mean when you are saying it's a const function
is that the this object is constant. So how about that?
const(this) int getFoo() { return foo; }
(It's syntactically unambiguous because this is a keyword)
-- Reiner

Yeah, I guess there are a lot of tradeoffs with each syntax. I was
wondering what the function pointers would look like as well...
const int function() p; // Current
const(this) int function() p; // Could be confusing in a member function
int const(function)() p; // Looks like a const function pointer
int function() const p; // C++ style
And combinations...
const(const const(int) function(const(int))) p;
const(const(this) const(int) function(const(int))) p;
const(const(int) const(function)(const(int))) p;
const(const(int) function(const(int)) const) p;
But the latter isn't really valid material for comparison. Anyways, I
think the bikeshed should be orange! ;)

I don't know if I'm missing something, but I thought that const
functions *only* exist as member functions. By which I mean that only
the following makes sense:
(supposing, for the purposes of this post, we adopt the existing C++ syntax)
class Foo
{
int getX() const
{ return x; }
}
It doesn't make sense declare a free function const, and it doesn't make
sense to declare a function pointer (or delegate type) const.
The reason I like my syntax (at risk of being too self-centred ;) ) is
that it highlights exactly what a const member function is: one with the
'this' pointer declared 'const'. I also can imagine future extensions of
this syntax to express globally pure functions, with something like
const(scope) or const(module). (Although they don't quite capture the
essence of const(world) :-) )
-- Reiner

Just chiming in on a slightly different note... the line that stuck out
in both examples for me was actually the const(func) line. That seems
really intuitive and consistent with the const syntax elsewhere.
I do find the const-on-the-end readable too, but really mostly because of
familiarity with C++ ;)

Although the idea is nice, I tried it out, and I don't like the look of
it:
int const(getFoo)() { return foo; }
My main objection is that the const() is around getFoo, so you're saying
that the function won't change -- but how can it, it's static data. What
you really mean when you are saying it's a const function is that the this
object is constant. So how about that?
const(this) int getFoo() { return foo; }
(It's syntactically unambiguous because this is a keyword)

Ok, same list as above, once again, this time using const(this) for method
constness (and dropping the const(func) from the list):
const(this) const(P) func (P p)
const(P) const(this) func (P p)
const(P) func const(this) (P p)
const(P) func:const(this) (P p)
const(P) func (P p) const(this)
Personally, I find all of these quite unreadable this time around, although
I guess I could get used to it. Too many parenthesized consts.
I'll do even a list with the parameter of the function as a const:
const(this) const(P) func (const(P) p)
const(P) const(this) func (const(P) p)
const(P) func const(this) (const(P) p)
const(P) func:const(this) (const(P) p)
const(P) func (const(P) p) const(this)
This is getting to where my eyes start to bleed. ;)
I'd still have to say that the cleanest syntax, at least to me, seems to be
the last one, with the method constness indicator after the parameter list.

I've got some ideas about how to make the const syntax more
consistent.
First I will show you the current situation.
Then I will list the confusions and possible solutions.
Some days ago I already mentioned my first idea on IRC, but got no
replies.
Also I know that you, Walter, hardly don't change features, which
already have been implemented.
And my suggestions would require this of course.
The "define proposal" is not such a big change in the language,
in opposite to the much more important idea about
"putting the return type in a bracket at the end".
Because this is what the last idea requires, it's written after "WAIT:".
Nevertheless I will give it a try, because 2.0 is still alpha and it
will break code compatibility anyway.
currently the keyword const(/invariant) has three meanings:
-----------------------------------------------------------
1. alone: const x = 1; compile-time variable (not an lvalue)

Well technically if that was what I wanted, I'd use one of 'invariant x
= 1;' or a more explicit 'final invariant(int) x = 1;'.

#3 is an issue, in my book. Not a massive one, but its there. We'll
get into that one below.

confusions and solutions:
-------------------------
#1
1. const x = 1;
2. const(P) p = new Point(1,2);
you see const first and later recognize the brackets
one would not expect brackets to lead to a completely different
meaning of the forrun keyword

My eyes are trained to spot them... still yes, a sudden shift in meaning
can be counter-intuitive. Although its not entirely a shift... you
could probably think of 'const x = 1;' as shorthand for 'final
const(int) x = 1;'.

Adding new keywords is usually the absolute last option around here.
(There was talk ages past of replacing 'auto x = 1' with 'let x = 1'.)

You might think about spoken languages: You learn more vocabularies to
be able to differentiate better, so you are more capable to express what
you mean, instead of relying on an absolutely small subset of vocabularies.
PS: "auto" also was a new keyword some time ago ;)
"define" is also known from C/C++ world to define something you can't
change, equivalent to what const x = 1; acutally means: not an lvalue.
In my opinion it's better to have a different keyword for something
different, and "define" makes much sense for me.

Uhm. Ew. No, seriously, I just could not possibly handle that; I would
keep thinking I saw templates where there aren't any. Worse yet, for a
long time I'll see the '!(' and keep wondering how I could be
instantiating a template in that position, when its really a template
declaration. T'is a naughty naughty thing to mix the two -- would give
both the compiler and the user headaches. IMHO, its the

I would suggest
const: P func (P p) { ... }
Not allowed:
const:
... func1 ...
... func2 ...
You always have to explicitly mention the "const:" for each function.
This way the "attribute feeling" is retained.

#3
1. same meaning: invariant x = 1; const x = 1;

For basic types, there often isn't much difference anyhow. Except that
invariant members of structures allocate no memory in the structure, for
example.

not allowed anymore: const(/invariant) alone is an attribute, instead
use:
1. define x = 1;
#4
//this is ok: final int x = 1; const(int)* xptr = &x; // but:
2. const(int) x = 1;
this is nonsense and also atm it could be confused with:
1. const int x = 1;
the compiler should issue at least a warning, and instead you should use:
1. define x = 1;
#5
void func(const P p) { typeof(p) == const(P) }
bad, because one could expect this to be also valid then:
const P p = new P(1,2); //but fails of course
correctly is has to be:
void func(const(P) p) { ... }
void func(ref const(P) p) { p = new P(3,4); } //OK
//void func(const(int) i) { ... } //const(int) nonsense (see #4)
//void func(ref const(int) i) { ... } //const(int) nonsense (see #4)
compiler should issue an error
const(/invariant) alone is an attribute
WAIT:
-----
because we have another syntax for compile-time variables now,
we could say that:
const P** ptr2ptr2P means:
const(P**) ptr2ptr2P
in this case, #5 would be allowed
but this would also require #2 further proposal to be implemented,
because if it wasn't:
const P** func() { ... }
would not only be confused with, but it would be THE SAME as:
const(P**) func() { ... }
then the correct form would have to be:
const func() (const P**) { ...}
note that #4 would be true for: const int x = 1; then
this would be nonsense, because it would be the same as: const(int) x
= 1;
so the compiler should issue at least a warning
PS: Having the return types in a bracket at the end, would make it
possible to implement multiple return values / return tuples
in a consistent way, too.
It would also allow more tricks, like returning local values of a
function, avoiding ref, etc etc ...
I would really enjoy to get some replies (especially yours, Walter),
even if it's just a: "No that's totally stupid" ;)
Best regards,
Daniel

No that's totally stupid.
Ahh I'm just kidding. At least you're thinking about the situation and
offering suggestions. (And welcome to the tiny militia of 'const R
func()' syntax detractors. ;)) The final/const/invariant system needs
some good hammering yet -- although its off to a lovely start, danke
Walter.
-- Chris Nicholson-Sauls

Yes, there seem to be a lot of people not being very happy with the
current const syntax.
But I have not seen much concrete suggestion how to make it better.
Best regards,
Daniel

confusions and solutions:
-------------------------
#1
1. const x = 1;
2. const(P) p = new Point(1,2);
you see const first and later recognize the brackets
one would not expect brackets to lead to a completely different
meaning of the forrun keyword

My eyes are trained to spot them... still yes, a sudden shift in
meaning can be counter-intuitive. Although its not entirely a
shift... you could probably think of 'const x = 1;' as shorthand for
'final const(int) x = 1;'.

But they are not the same:
const x = 1;
doesn't take up space
final const(int) x = 1;
does take up space

Just like 'invariant' does. Gotcha. Maybe the rule should be as I
"suggested" with the implication that 'final' values of a basic type and
an in-place initializer do not take up space? Or at least in the
context of final+const|invariant.
Then again, the current behavior at least works.

Adding new keywords is usually the absolute last option around here.
(There was talk ages past of replacing 'auto x = 1' with 'let x = 1'.)

You might think about spoken languages: You learn more vocabularies to
be able to differentiate better, so you are more capable to express what
you mean, instead of relying on an absolutely small subset of vocabularies.
PS: "auto" also was a new keyword some time ago ;)
"define" is also known from C/C++ world to define something you can't
change, equivalent to what const x = 1; acutally means: not an lvalue.
In my opinion it's better to have a different keyword for something
different, and "define" makes much sense for me.

Granted; I'm just saying it'll be more work to sell a new keyword. Your
nomination of 'define' is itself sound. (I'm sure we'll never get the
Ruby rule of "just start the name with a capital letter". ;))

You are right, it really looks like a template instatiation.
So lets try without the ! on declaration:
func(T) (T var) (T) //IFTI take T return T
func(T) (T var) //IFTI take T
func(T) () (T) //IFTI return T
func(T) //IFTI
func(T var) (T) // take T return T
func(T var) // take T
func() (T) // return T
func() //
At least one () should remain, to make clear that it's a function
Before the return brackets there must always be the take brackets.
So 4. can only mean IFTI.
This looks good in my opinion.

Its... different. And I suppose workable, particularly if it were made
optional -- that is, let the current syntax stand, and allow this as an
alternate syntax. I do like the idea of:
func() { ... }
Being apparently equivelant to:
void func() { ... }
I think perhaps I'm just too "fond" (ie, comfortable, familiar) with the
'M... R func(A)' syntax and therefore scared to change it. Especially
since it'd be a radical change at this point in the game. (At least for
D/1.0)

I would suggest
const: P func (P p) { ... }
Not allowed:
const:
... func1 ...
... func2 ...
You always have to explicitly mention the "const:" for each function.
This way the "attribute feeling" is retained.

Actually... I like it.

[snip] At least you're thinking about the situation
and offering suggestions. (And welcome to the tiny militia of 'const
R func()' syntax detractors. ;)) The final/const/invariant system
needs some good hammering yet -- although its off to a lovely start,
danke Walter.

Yes, there seem to be a lot of people not being very happy with the
current const syntax.
But I have not seen much concrete suggestion how to make it better.

Its a tough nut to crack. Chances are we really need to just do
something crazy and new... its the coming-up-with-something-new part
that's hard.
A 'func(T...)(A...)(R)' function syntax, though. Now that's new. :)
-- Chris Nicholson-Sauls

Yes, there seem to be a lot of people not being very happy with the
current const syntax.
But I have not seen much concrete suggestion how to make it better.

Its a tough nut to crack. Chances are we really need to just do
something crazy and new... its the coming-up-with-something-new part
that's hard.
A 'func(T...)(A...)(R)' function syntax, though. Now that's new. :)
-- Chris Nicholson-Sauls

It's not that it's a bad idea, but there's some inner aversion to it in me.
[Return type] [name] [args] has been a staple of C-based languages (and,
indeed, strongly-typed languages in general).
Personally, I like the const semantics except:
- Compile time constants should be "invariant" only.
invariant int x = 3;
const int y = 3;
Both x and y are compile-time constants...
- Class invarinats should be better disambiguated. Personally, I like the idea
of "readonly" replacing cost and "const" replacing invariant, with invariant
reserved for class invarinats (thus keeping some degree of backwards
compatibility).

I love the 'define' proposal. It is totally unambiguous and clear what is
intended by the code writer, and totally unambiguous and clear about what
we expect of the compiler.
--
Derek Parnell
Melbourne, Australia
"Down with mediocrity!"

I love the 'define' proposal. It is totally unambiguous and clear what is
intended by the code writer, and totally unambiguous and clear about what
we expect of the compiler.

What I think would really rock is if 'define' could also be used for
types and maybe expressions.
I've long felt it was silly that aliases were backwards from normal
assignments.
define x = 1;
define myInt = int;
I'd love that.
Then just get rid of alias. :-)
Or maybe just allow alias to use either syntax:
alias x = 1;
alias 1 x;
alias myInt = some_complex_expr_to_compute_a_type!(int);
alias some_complex_expr_to_compute_a_type!(int) myInt;
In my opinion it's a lot easier to read the assignment syntax (alias
sym=thing) than the current alias syntax (alias thing sym). Mainly
because, as you see above, often the 'thing' is really long, but usually
the 'sym' is something very short. It makes it easier to see the thing
you care about in the end which is the sym that comes out of the
statement that you'll be using in subsequent code.
--bb

I love the 'define' proposal. It is totally unambiguous and clear what is
intended by the code writer, and totally unambiguous and clear about what
we expect of the compiler.

What I think would really rock is if 'define' could also be used for
types and maybe expressions.
I've long felt it was silly that aliases were backwards from normal
assignments.
define x = 1;
define myInt = int;
I'd love that.
Then just get rid of alias. :-)
Or maybe just allow alias to use either syntax:
alias x = 1;
alias 1 x;
alias myInt = some_complex_expr_to_compute_a_type!(int);
alias some_complex_expr_to_compute_a_type!(int) myInt;
In my opinion it's a lot easier to read the assignment syntax (alias
sym=thing) than the current alias syntax (alias thing sym). Mainly
because, as you see above, often the 'thing' is really long, but usually
the 'sym' is something very short. It makes it easier to see the thing
you care about in the end which is the sym that comes out of the
statement that you'll be using in subsequent code.
--bb

As I understand it, the reason alias syntax is like this, is so the compiler
can simply
parse the alias as though it were a normal 'Type symbol;' decleration -- just
like
variables and functions (up until argument lists). That said, I don't imagine
it would be
difficult to have something of a separator in there instead, either '=' as
suggested or
even ':' as used to specify inheritance of classes and enums. Hmm. In fact,
maybe have
'=' expect an expression to define a compile-time constant, and ':' expect a
type to
define an alias as per current behavior.
alias x = 1 ;
alias myInt : some_complex_expr_to_compute_a_type!(int) ;
Just thinking "aloud."
-- Chris Nicholson-Sauls

Or maybe just allow alias to use either syntax:
alias x = 1;
alias 1 x;
alias myInt = some_complex_expr_to_compute_a_type!(int);
alias some_complex_expr_to_compute_a_type!(int) myInt;
In my opinion it's a lot easier to read the assignment syntax (alias
sym=thing) than the current alias syntax (alias thing sym). Mainly
because, as you see above, often the 'thing' is really long, but usually
the 'sym' is something very short. It makes it easier to see the thing
you care about in the end which is the sym that comes out of the
statement that you'll be using in subsequent code.
--bb

I think that would be just great. I hate having to write two templates,
one for values and one for aliases. It's quite un-generic. A good
example is the identity function that Andrei is keen on. It's a fair bit
of work to write with templates, so that it works with types, values,
and expression aliases:
template Identity(T...)
{
static if (!is(T[0]))
const Identity = T[0];
else
alias T[0] Identity;
}
// testing
static assert(is(Identity!(int) == int));
static assert(Identity!(5) == 5);
int x;
void main()
{
Identity!(x) = Identity!(5);
assert(x == 5);
}
This currently works, but I'm not sure why[1], and it is annoying to
require that. I would like to be able to write
template Identity(T...)
{
alias T[0] Identity;
}
but that currently doesn't work when T[0] is a value parameter.
This does actually cause problems with writing compile-time util
templates, like FoldR:
template FoldR(alias Fn, T...)
{
static if (T.length == 0)
static assert(false, "Must have starting case for FoldR");
else static if (T.length == 1)
{
static if (is(T[0]))
alias T[0] FoldR;
else
const FoldR = T[0];
}
else
{
// I have to repeat this ugly recursive instantiation 3 times
// because I can't keep the result -- do I alias it or use const?
static if (is(FoldR!(Fn, Fn!(T[0], T[1]).val, T[2..$])))
alias FoldR!(Fn, Fn!(T[0], T[1]).val, T[2..$]) FoldR;
else
const FoldR = FoldR!(Fn, Fn!(T[0], T[1]).val, T[2..$]);
}
}
So I think having alias work for values as well as types/symbols would
be great. I'm not so fussed either way about
alias x = int;
I can see it reads better in some situations, though, and I don't see it
causing any problems if both were allowed.
-- Reiner
[1] Here's what's confusing me (I expect it's a bug). In the first code
snippet I posted, the !is(T[0]) means that types are aliased, which is
good, but the call to Identity!(x) doesn't use the alias, it uses the
const Identity = T[0]; part. So what is happening is effectively this:
// in the instantiation of Identity!(x)
const Identity = x;
// in main()
Identity!(x).Identity = 5;
We're reassigning a constant -- how does that work? -- but somehow that
causes x to change... it's oddly doing the alias itself...

I realize there are some consistency issues with the current syntax for
const, but it is more complicated than expected. Your idea to separate
out compile time constants with a new keyword is a good one, and is
similar to one Andrei came up with (using alias).

I realize there are some consistency issues with the current syntax for
const, but it is more complicated than expected. Your idea to separate
out compile time constants with a new keyword is a good one, and is
similar to one Andrei came up with (using alias).

I hadn't even considered alias. Was his idea roughly that have having
"two" aliases, one of the form 'alias symbol symbol' and the other
'alias expression symbol'? Depending on how difficult it would be to
implement, it might just work.
If it was something else entirely, then I missed that one.
-- Chris Nicholson-Sauls

I realize there are some consistency issues with the current syntax for
const, but it is more complicated than expected. Your idea to separate
out compile time constants with a new keyword is a good one, and is
similar to one Andrei came up with (using alias).