www.digitalmars.com         C & C++   DMDScript  

digitalmars.D - const/immutable member functions

reply Trass3r <un known.com> writes:
class F
{
const Foo bar();
}

Isn't this ambiguous? "returns a const Foo object" vs. "is a const
member function that returns a Foo object"?
Jan 24 2011
next sibling parent reply "Simen kjaeraas" <simen.kjaras gmail.com> writes:
Trass3r <un known.com> wrote:

 class F
 {
 const Foo bar();
 }

 Isn't this ambiguous? "returns a const Foo object" vs. "is a const
 member function that returns a Foo object"?
Only to humans. const applies to everything after it, unless there are parentheses. In this case, 'everything' is Foo bar(); I do agree it is ambiguous though, and should be disallowed, or at very least, discouraged. -- Simen
Jan 24 2011
next sibling parent reply Jonathan M Davis <jmdavisProg gmx.com> writes:
On Monday 24 January 2011 06:02:13 Simen kjaeraas wrote:
 Trass3r <un known.com> wrote:
 class F
 {
 const Foo bar();
 }
 
 Isn't this ambiguous? "returns a const Foo object" vs. "is a const
 member function that returns a Foo object"?
Only to humans. const applies to everything after it, unless there are parentheses. In this case, 'everything' is Foo bar();
Not quite right. The return value is _not_ const in this case. It's only the function which is affected. Try it and you'll see. The _only_ time that a return value is const or immutable is if you use parens to mark it that way. - Jonathan M Davis
Jan 24 2011
parent "Simen kjaeraas" <simen.kjaras gmail.com> writes:
Jonathan M Davis <jmdavisProg gmx.com> wrote:

 Only to humans. const applies to everything after it, unless there
 are parentheses. In this case, 'everything' is Foo bar();
Not quite right. The return value is _not_ const in this case. It's only the function which is affected. Try it and you'll see. The _only_ time that a return value is const or immutable is if you use parens to mark it that way.
I could probably have worded that more clearly. *clears throat* const applies to one, and exactly one, thing after it, matched greedily. So yes, Foo bar() is the 'everything'. Foo and Foo bar() would be two things. -- Simen
Jan 24 2011
prev sibling parent Jens Mueller <jens.k.mueller gmx.de> writes:
Simen kjaeraas wrote:
 Trass3r <un known.com> wrote:
 
class F
{
const Foo bar();
}

Isn't this ambiguous? "returns a const Foo object" vs. "is a const
member function that returns a Foo object"?
Only to humans. const applies to everything after it, unless there are parentheses. In this case, 'everything' is Foo bar(); I do agree it is ambiguous though, and should be disallowed, or at very least, discouraged.
Very true. Preferred style is to write Foo bar() const; Jens
Jan 24 2011
prev sibling next sibling parent reply Jonathan M Davis <jmdavisProg gmx.com> writes:
On Monday 24 January 2011 05:56:49 Trass3r wrote:
 class F
 {
 const Foo bar();
 }
 
 Isn't this ambiguous? "returns a const Foo object" vs. "is a const
 member function that returns a Foo object"?
When using const or immutable in a function signature, it _always_ applies to the function, unless you use parens to say otherwise. const Foo bar(); //const function Foo bar() const; //const function immutable Foo bar(); //immutable function Foo bar() immutable; //immutable function const(Foo) bar(); //mutable function with const return value const(Foo) bar() const; //const function with const return value immutable(Foo) bar(); //mutable function with immutable return value immutable(Foo) bor() immutable; //immutable function with immutable return value And, of course, you could mix up const and immutable to have const functions with immutable return values and vice versa. Personally, I don't like it. In fact, most people don't, but that's the way it is. I always put const and immutable or the right-hand side of the function when I want the function to be const or immutable, and I wish that that were required, but it isn't. It's the way it is because it's consistent with all of the other function modifiers: property, nothrow, public, static, etc. In fact, ddoc always put them all in front of the function signature, even if you put them after. So, if you want the return value to be const or immutable, use parens. Otherwise it's the function. If you want both to be const and/or immutable, then you need to mark them both that way. - Jonathan M Davis
Jan 24 2011
parent reply "Steven Schveighoffer" <schveiguy yahoo.com> writes:
On Mon, 24 Jan 2011 09:20:17 -0500, Jonathan M Davis <jmdavisProg gmx.com>  
wrote:

 On Monday 24 January 2011 05:56:49 Trass3r wrote:
 class F
 {
 const Foo bar();
 }

 Isn't this ambiguous? "returns a const Foo object" vs. "is a const
 member function that returns a Foo object"?
When using const or immutable in a function signature, it _always_ applies to the function, unless you use parens to say otherwise. const Foo bar(); //const function Foo bar() const; //const function immutable Foo bar(); //immutable function Foo bar() immutable; //immutable function const(Foo) bar(); //mutable function with const return value const(Foo) bar() const; //const function with const return value immutable(Foo) bar(); //mutable function with immutable return value immutable(Foo) bor() immutable; //immutable function with immutable return value
You forget my favorite: const const Foo bar(); // const function returning const Foo. -Steve
Jan 24 2011
next sibling parent reply Jonathan M Davis <jmdavisProg gmx.com> writes:
On Monday 24 January 2011 06:27:34 Steven Schveighoffer wrote:
 On Mon, 24 Jan 2011 09:20:17 -0500, Jonathan M Davis <jmdavisProg gmx.com>
 
 wrote:
 On Monday 24 January 2011 05:56:49 Trass3r wrote:
 class F
 {
 const Foo bar();
 }
 
 Isn't this ambiguous? "returns a const Foo object" vs. "is a const
 member function that returns a Foo object"?
When using const or immutable in a function signature, it _always_ applies to the function, unless you use parens to say otherwise. const Foo bar(); //const function Foo bar() const; //const function immutable Foo bar(); //immutable function Foo bar() immutable; //immutable function const(Foo) bar(); //mutable function with const return value const(Foo) bar() const; //const function with const return value immutable(Foo) bar(); //mutable function with immutable return value immutable(Foo) bor() immutable; //immutable function with immutable return value
You forget my favorite: const const Foo bar(); // const function returning const Foo.
That works? I would have thought that it still would have required the parens. Regardless, const and immutable on functions is not the cleanest corner of D. It's fairly easily understood and mostly doesn't result in bugs because marking the wrong thing as const usually results in a compilation error somewhere, but still, it would be nice if const and immutable had to go on the right-hand side like they do in C++. - Jonathan M Davis
Jan 24 2011
parent "Steven Schveighoffer" <schveiguy yahoo.com> writes:
On Mon, 24 Jan 2011 09:39:16 -0500, Jonathan M Davis <jmdavisProg gmx.com>  
wrote:

 On Monday 24 January 2011 06:27:34 Steven Schveighoffer wrote:
 On Mon, 24 Jan 2011 09:20:17 -0500, Jonathan M Davis  
 <jmdavisProg gmx.com>

 wrote:
 On Monday 24 January 2011 05:56:49 Trass3r wrote:
 class F
 {
 const Foo bar();
 }

 Isn't this ambiguous? "returns a const Foo object" vs. "is a const
 member function that returns a Foo object"?
When using const or immutable in a function signature, it _always_ applies to the function, unless you use parens to say otherwise. const Foo bar(); //const function Foo bar() const; //const function immutable Foo bar(); //immutable function Foo bar() immutable; //immutable function const(Foo) bar(); //mutable function with const return value const(Foo) bar() const; //const function with const return value immutable(Foo) bar(); //mutable function with immutable return value immutable(Foo) bor() immutable; //immutable function with immutable return value
You forget my favorite: const const Foo bar(); // const function returning const Foo.
That works? I would have thought that it still would have required the parens.
I could have sworn it does, but on testing (which I probably should have done), it fails (even back on 2.033) with: redundant storage class const Sorry for the noise, I still find the const const(Foo) bar() very confusing to read. -Steve
Jan 24 2011
prev sibling next sibling parent Andrej Mitrovic <andrej.mitrovich gmail.com> writes:
Perhaps it would be less ambiguous if we turned const/immutable for
functions into annotations:

 const Foo bar(); //const function
 immutable Foo bar(); //immutable function
 immutable const(Foo) bar(); //immutable function with const return value
 const const(Foo) bar(); //const function with const return value
immutable(Foo) bar(); //mutable function with immutable return value
 immutable immutable(Foo) bor(); //immutable function with immutable
return value

But I'm not a big fan of " ", it clutters up source code.
Jan 24 2011
prev sibling parent Jonathan M Davis <jmdavisProg gmx.com> writes:
On Monday 24 January 2011 06:45:27 Andrej Mitrovic wrote:
 Perhaps it would be less ambiguous if we turned const/immutable for
 functions into annotations:
 
  const Foo bar(); //const function
  immutable Foo bar(); //immutable function
  immutable const(Foo) bar(); //immutable function with const return value
  const const(Foo) bar(); //const function with const return value
 immutable(Foo) bar(); //mutable function with immutable return value
  immutable immutable(Foo) bor(); //immutable function with immutable
 return value
 
 But I'm not a big fan of " ", it clutters up source code.
Well, any change to the situation would break TDPL, I believe, so we're pretty much stuck. If Walter didn't think it was bad enough to fix by now, he won't fix it post-TDPL. - Jonathan M Davis
Jan 24 2011
prev sibling next sibling parent Kagamin <spam here.lot> writes:
Trass3r Wrote:

 class F
 {
 const Foo bar();
 }
 
 Isn't this ambiguous? "returns a const Foo object" vs. "is a const
 member function that returns a Foo object"?
The const qualifier applies to the member being declared - the function in this case. Usually transitivity rules come into play, but they're not defined for functions.
Jan 24 2011
prev sibling next sibling parent reply bearophile <bearophileHUGS lycos.com> writes:
There are six, seven or more people that wish to do something about this
situation. TDPL is the D2 reference, but few little changes over its first
edition are acceptable if they improve the D language a little.

- Trass3r: asks if the code is ambiguous
- Jonathan M Davis: does't like it and puts const/etc on the right
- Simen kjaeraas thinks it's ambiguous though, and should be disallowed, or at
very least, discouraged.
- Jens Mueller: Preferred style is to write const on the right
- Andrej Mitrovic suggests to use   but says it clutters up source code.
- I agree with Jonathan M Davis.

What other people think about this situation? Do you want const/immutable to be
required on the right, or do you prefer the current situation, or do you prefer
some other solution?

This is the bug report, that Walter has closed, but if necessary it may be
opened up again if enough people are interested in the topic:
http://d.puremagic.com/issues/show_bug.cgi?id=4070

See also:
http://d.puremagic.com/issues/show_bug.cgi?id=4040

Bye,
bearophile
Jan 24 2011
next sibling parent reply Torarin <torarind gmail.com> writes:
2011/1/24 bearophile <bearophileHUGS lycos.com>:
 What other people think about this situation? Do you want const/immutable to
be required on the right, or do you prefer the current situation, or do you
prefer some other solution?
If const is required to go on the right, what do you do if you want to mark a bunch of functions const inside {}? Torarin
Jan 24 2011
next sibling parent so <so so.do> writes:
On Mon, 24 Jan 2011 20:41:17 +0200, Torarin <torarind gmail.com> wrote:

 2011/1/24 bearophile <bearophileHUGS lycos.com>:
 What other people think about this situation? Do you want  
 const/immutable to be required on the right, or do you prefer the  
 current situation, or do you prefer some other solution?
If const is required to go on the right, what do you do if you want to mark a bunch of functions const inside {}? Torarin
I love that one, it is also quite explicit, we should definitely keep it. But i agree with all that the other case should be disallowed.
Jan 24 2011
prev sibling parent reply "Simen kjaeraas" <simen.kjaras gmail.com> writes:
Torarin <torarind gmail.com> wrote:

 2011/1/24 bearophile <bearophileHUGS lycos.com>:
 What other people think about this situation? Do you want  
 const/immutable to be required on the right, or do you prefer the  
 current situation, or do you prefer some other solution?
If const is required to go on the right, what do you do if you want to mark a bunch of functions const inside {}?
The suggestion is only for const alone on the left-hand side. const: and const{} would not be affected by such a change. That said, I consider const Foo bar(); to be a bug, and mercilessly squish it. I always put const on the right side of functions, and should I ever write coding guidelines for D, putting it on the left would be a capital offense. -- Simen
Jan 24 2011
parent Torarin <torarind gmail.com> writes:
2011/1/24 Simen kjaeraas <simen.kjaras gmail.com>:
 The suggestion is only for const alone on the left-hand side. const: and
 const{} would not be affected by such a change.
You're right, it's not confusing at all. It makes perfect sense for function attributes to go on the right. But then I'd like all of them to go there, like Jonathan suggested. Torarin
Jan 24 2011
prev sibling next sibling parent reply "Steven Schveighoffer" <schveiguy yahoo.com> writes:
On Mon, 24 Jan 2011 13:36:36 -0500, bearophile <bearophileHUGS lycos.com>  
wrote:

 There are six, seven or more people that wish to do something about this  
 situation. TDPL is the D2 reference, but few little changes over its  
 first edition are acceptable if they improve the D language a little.

 - Trass3r: asks if the code is ambiguous
 - Jonathan M Davis: does't like it and puts const/etc on the right
 - Simen kjaeraas thinks it's ambiguous though, and should be disallowed,  
 or at very least, discouraged.
 - Jens Mueller: Preferred style is to write const on the right
 - Andrej Mitrovic suggests to use   but says it clutters up source code.
 - I agree with Jonathan M Davis.

 What other people think about this situation? Do you want  
 const/immutable to be required on the right, or do you prefer the  
 current situation, or do you prefer some other solution?
I wouldn't say that I *prefer* the current solution, but the current solution is not so bad that I need it changed. It works fine, despite being confusing. If it wasn't consistent with the rest of the attributes, I'd say it was in need of changes, but it fits within the scheme already outlined. I think we have more important problems to worry about than this. -Steve
Jan 24 2011
next sibling parent so <so so.do> writes:
 I think we have more important problems to worry about than this.
IMHO fixing trivial issues first or as soon as possible is better. Not saying this is one of them, i mean generally.
Jan 24 2011
prev sibling next sibling parent Trass3r <un known.com> writes:
 I wouldn't say that I *prefer* the current solution, but the current  
 solution is not so bad that I need it changed.

 It works fine, despite being confusing.  If it wasn't consistent with  
 the rest of the attributes, I'd say it was in need of changes, but it  
 fits within the scheme already outlined.

 I think we have more important problems to worry about than this.

 -Steve
I'm not sure either but I usually use the suffix version. The question is if there is any case where the prefix one could be harmful (i.e. not resulting in an error message). Maybe the following?: class Foo { private static Bar[] bar; // author thinks it returns a const pointer etc. const Foo* ptr() { return bar.ptr; } }
Jan 24 2011
prev sibling next sibling parent reply Don <nospam nospam.com> writes:
Steven Schveighoffer wrote:
 On Mon, 24 Jan 2011 13:36:36 -0500, bearophile 
 <bearophileHUGS lycos.com> wrote:
 
 There are six, seven or more people that wish to do something about 
 this situation. TDPL is the D2 reference, but few little changes over 
 its first edition are acceptable if they improve the D language a little.

 - Trass3r: asks if the code is ambiguous
 - Jonathan M Davis: does't like it and puts const/etc on the right
 - Simen kjaeraas thinks it's ambiguous though, and should be 
 disallowed, or at very least, discouraged.
 - Jens Mueller: Preferred style is to write const on the right
 - Andrej Mitrovic suggests to use   but says it clutters up source code.
 - I agree with Jonathan M Davis.

 What other people think about this situation? Do you want 
 const/immutable to be required on the right, or do you prefer the 
 current situation, or do you prefer some other solution?
I wouldn't say that I *prefer* the current solution, but the current solution is not so bad that I need it changed. It works fine, despite being confusing. If it wasn't consistent with the rest of the attributes, I'd say it was in need of changes, but it fits within the scheme already outlined.
It's a problem for all of the other attributes as well. I wish it were disallowed for all of them. Incidentally, putting it afterwards always works. Putting it before doesn't always work, due to compiler bugs (for example, prefix 'pure' doesn't work for inner functions).
Jan 24 2011
next sibling parent Jonathan M Davis <jmdavisProg gmx.com> writes:
On Monday 24 January 2011 12:08:29 Don wrote:
 Steven Schveighoffer wrote:
 On Mon, 24 Jan 2011 13:36:36 -0500, bearophile
 
 <bearophileHUGS lycos.com> wrote:
 There are six, seven or more people that wish to do something about
 this situation. TDPL is the D2 reference, but few little changes over
 its first edition are acceptable if they improve the D language a
 little.
 
 - Trass3r: asks if the code is ambiguous
 - Jonathan M Davis: does't like it and puts const/etc on the right
 - Simen kjaeraas thinks it's ambiguous though, and should be
 disallowed, or at very least, discouraged.
 - Jens Mueller: Preferred style is to write const on the right
 - Andrej Mitrovic suggests to use   but says it clutters up source code.
 - I agree with Jonathan M Davis.
 
 What other people think about this situation? Do you want
 const/immutable to be required on the right, or do you prefer the
 current situation, or do you prefer some other solution?
I wouldn't say that I *prefer* the current solution, but the current solution is not so bad that I need it changed. It works fine, despite being confusing. If it wasn't consistent with the rest of the attributes, I'd say it was in need of changes, but it fits within the scheme already outlined.
It's a problem for all of the other attributes as well. I wish it were disallowed for all of them. Incidentally, putting it afterwards always works. Putting it before doesn't always work, due to compiler bugs (for example, prefix 'pure' doesn't work for inner functions).
There there is a bug that attributes on constructors don't show up in generated .di files if they're on the right. I think that the real problem with putting them all on the right is that attributes such as static, public, and private are on the left in other languages, so it would be really weird to require that they be on the right. Still, it might be worth it. - Jonathan M Davis
Jan 24 2011
prev sibling parent Jens Mueller <jens.k.mueller gmx.de> writes:
Jonathan M Davis wrote:
 On Monday 24 January 2011 12:08:29 Don wrote:
 Steven Schveighoffer wrote:
 On Mon, 24 Jan 2011 13:36:36 -0500, bearophile
 
 <bearophileHUGS lycos.com> wrote:
 There are six, seven or more people that wish to do something about
 this situation. TDPL is the D2 reference, but few little changes over
 its first edition are acceptable if they improve the D language a
 little.
 
 - Trass3r: asks if the code is ambiguous
 - Jonathan M Davis: does't like it and puts const/etc on the right
 - Simen kjaeraas thinks it's ambiguous though, and should be
 disallowed, or at very least, discouraged.
 - Jens Mueller: Preferred style is to write const on the right
 - Andrej Mitrovic suggests to use   but says it clutters up source code.
 - I agree with Jonathan M Davis.
 
 What other people think about this situation? Do you want
 const/immutable to be required on the right, or do you prefer the
 current situation, or do you prefer some other solution?
I wouldn't say that I *prefer* the current solution, but the current solution is not so bad that I need it changed. It works fine, despite being confusing. If it wasn't consistent with the rest of the attributes, I'd say it was in need of changes, but it fits within the scheme already outlined.
It's a problem for all of the other attributes as well. I wish it were disallowed for all of them. Incidentally, putting it afterwards always works. Putting it before doesn't always work, due to compiler bugs (for example, prefix 'pure' doesn't work for inner functions).
There there is a bug that attributes on constructors don't show up in generated .di files if they're on the right. I think that the real problem with putting them all on the right is that attributes such as static, public, and private are on the left in other languages, so it would be really weird to require that they be on the right. Still, it might be worth it.
Can't one have only the type qualifiers on the right? I mean it's only confusing for those. pure/nothrow int foo(); causes no confusion at all. The access qualifiers also work fine in the beginning. On the right they won't even compile. Jens
Jan 24 2011
prev sibling parent bearophile <bearophileHUGS lycos.com> writes:
Steven Schveighoffer:

 I think we have more important problems to worry about than this.
I agree. On the other hand in other languages I've seen that many small troubles pile up and reduce the enjoyment of using a language. Bye, bearophile
Jan 24 2011
prev sibling next sibling parent spir <denis.spir gmail.com> writes:
On 01/24/2011 07:36 PM, bearophile wrote:
 What other people think about this situation? Do you want const/immutable to
be required on the right, or do you prefer the current situation, or do you
prefer some other solution?
Comparing with C-like typing syntax that, I guess, are planned for deprecation: C typing is not wrong, ambiguous, just arguably more difficult to decode, and unnecessary because we have a better alternative. IIUC, prefixed const and the like instead are not only unnecessary, but inherently ambiguous. Denis -- _________________ vita es estrany spir.wikidot.com
Jan 24 2011
prev sibling next sibling parent Jonathan M Davis <jmdavisProg gmx.com> writes:
On Monday 24 January 2011 13:52:49 Jens Mueller wrote:
 Jonathan M Davis wrote:
 On Monday 24 January 2011 12:08:29 Don wrote:
 Steven Schveighoffer wrote:
 On Mon, 24 Jan 2011 13:36:36 -0500, bearophile
 
 <bearophileHUGS lycos.com> wrote:
 There are six, seven or more people that wish to do something about
 this situation. TDPL is the D2 reference, but few little changes
 over its first edition are acceptable if they improve the D
 language a little.
 
 - Trass3r: asks if the code is ambiguous
 - Jonathan M Davis: does't like it and puts const/etc on the right
 - Simen kjaeraas thinks it's ambiguous though, and should be
 disallowed, or at very least, discouraged.
 - Jens Mueller: Preferred style is to write const on the right
 - Andrej Mitrovic suggests to use   but says it clutters up source
 code. - I agree with Jonathan M Davis.
 
 What other people think about this situation? Do you want
 const/immutable to be required on the right, or do you prefer the
 current situation, or do you prefer some other solution?
I wouldn't say that I *prefer* the current solution, but the current solution is not so bad that I need it changed. It works fine, despite being confusing. If it wasn't consistent with the rest of the attributes, I'd say it was in need of changes, but it fits within the scheme already outlined.
It's a problem for all of the other attributes as well. I wish it were disallowed for all of them. Incidentally, putting it afterwards always works. Putting it before doesn't always work, due to compiler bugs (for example, prefix 'pure' doesn't work for inner functions).
There there is a bug that attributes on constructors don't show up in generated .di files if they're on the right. I think that the real problem with putting them all on the right is that attributes such as static, public, and private are on the left in other languages, so it would be really weird to require that they be on the right. Still, it might be worth it.
Can't one have only the type qualifiers on the right? I mean it's only confusing for those. pure/nothrow int foo(); causes no confusion at all. The access qualifiers also work fine in the beginning. On the right they won't even compile.
I'm surprised that they don't work on the right. The argument for allowing const on the left-hand side has always been consistency - that all function attributes work the same. If that's not the case, then it seems to me like a definite argument for disallowing const on the left. - Jonathan m Davis
Jan 24 2011
prev sibling next sibling parent reply Jens Mueller <jens.k.mueller gmx.de> writes:
Jonathan M Davis wrote:
 On Monday 24 January 2011 13:52:49 Jens Mueller wrote:
 Jonathan M Davis wrote:
 On Monday 24 January 2011 12:08:29 Don wrote:
 Steven Schveighoffer wrote:
 On Mon, 24 Jan 2011 13:36:36 -0500, bearophile
 
 <bearophileHUGS lycos.com> wrote:
 There are six, seven or more people that wish to do something about
 this situation. TDPL is the D2 reference, but few little changes
 over its first edition are acceptable if they improve the D
 language a little.
 
 - Trass3r: asks if the code is ambiguous
 - Jonathan M Davis: does't like it and puts const/etc on the right
 - Simen kjaeraas thinks it's ambiguous though, and should be
 disallowed, or at very least, discouraged.
 - Jens Mueller: Preferred style is to write const on the right
 - Andrej Mitrovic suggests to use   but says it clutters up source
 code. - I agree with Jonathan M Davis.
 
 What other people think about this situation? Do you want
 const/immutable to be required on the right, or do you prefer the
 current situation, or do you prefer some other solution?
I wouldn't say that I *prefer* the current solution, but the current solution is not so bad that I need it changed. It works fine, despite being confusing. If it wasn't consistent with the rest of the attributes, I'd say it was in need of changes, but it fits within the scheme already outlined.
It's a problem for all of the other attributes as well. I wish it were disallowed for all of them. Incidentally, putting it afterwards always works. Putting it before doesn't always work, due to compiler bugs (for example, prefix 'pure' doesn't work for inner functions).
There there is a bug that attributes on constructors don't show up in generated .di files if they're on the right. I think that the real problem with putting them all on the right is that attributes such as static, public, and private are on the left in other languages, so it would be really weird to require that they be on the right. Still, it might be worth it.
Can't one have only the type qualifiers on the right? I mean it's only confusing for those. pure/nothrow int foo(); causes no confusion at all. The access qualifiers also work fine in the beginning. On the right they won't even compile.
I'm surprised that they don't work on the right. The argument for allowing const on the left-hand side has always been consistency - that all function attributes work the same. If that's not the case, then it seems to me like a definite argument for disallowing const on the left.
I do not know what are you referring to when you say function attributes. I distinguish the following: type qualifiers: const, immutable, maybe also inout function attributes: pure, nothrow storage class: ref, in, out, static access qualifiers: private, package, protected, public, export Storage class and access qualifies should go left only in my opinion and that's how dmd behaves. Function attributes can go left and right and I think there is nothing wrong with allowing that because there is no confusion. Even though I like them to be right as well. But this is matter of style. There is only confusion for type qualifies. Namely does the qualifier apply to the return type or the function (better said the type of this). Now it is consistent in the sense that const: int foo(); const { int foo(); } const int foo(); all mean the same. And Walter seems to be unsure whether forbidding const void foo() is worth the trouble, isn't it? I see and felt the pain for newcomers to decipher the meaning of const void foo(); I see two options: Either we clarify the documentation (e.g. examples) to help newcomers or we fix it in the front end. Picking the second option means to provide a patch and send it to review. Picking the first option means improving http://www.digitalmars.com/d/2.0/const3.html Jens
Jan 25 2011
parent bearophile <bearophileHUGS lycos.com> writes:
Jens Mueller:

 all mean the same. And Walter seems to be unsure whether forbidding
 const void foo() is worth the trouble, isn't it?
 I see and felt the pain for newcomers to decipher the meaning of
 const void foo();
 I see two options:
Now I'd like to know what Andrei thinks about this. Bye, bearophile
Jan 25 2011
prev sibling next sibling parent Jonathan M Davis <jmdavisProg gmx.com> writes:
On Tuesday 25 January 2011 01:45:49 Jens Mueller wrote:
 Jonathan M Davis wrote:
 On Monday 24 January 2011 13:52:49 Jens Mueller wrote:
 Jonathan M Davis wrote:
 On Monday 24 January 2011 12:08:29 Don wrote:
 Steven Schveighoffer wrote:
 On Mon, 24 Jan 2011 13:36:36 -0500, bearophile
 
 <bearophileHUGS lycos.com> wrote:
 There are six, seven or more people that wish to do something
 about this situation. TDPL is the D2 reference, but few little
 changes over its first edition are acceptable if they improve
 the D language a little.
 
 - Trass3r: asks if the code is ambiguous
 - Jonathan M Davis: does't like it and puts const/etc on the
 right - Simen kjaeraas thinks it's ambiguous though, and should
 be disallowed, or at very least, discouraged.
 - Jens Mueller: Preferred style is to write const on the right
 - Andrej Mitrovic suggests to use   but says it clutters up
 source code. - I agree with Jonathan M Davis.
 
 What other people think about this situation? Do you want
 const/immutable to be required on the right, or do you prefer
 the current situation, or do you prefer some other solution?
I wouldn't say that I *prefer* the current solution, but the current solution is not so bad that I need it changed. It works fine, despite being confusing. If it wasn't consistent with the rest of the attributes, I'd say it was in need of changes, but it fits within the scheme already outlined.
It's a problem for all of the other attributes as well. I wish it were disallowed for all of them. Incidentally, putting it afterwards always works. Putting it before doesn't always work, due to compiler bugs (for example, prefix 'pure' doesn't work for inner functions).
There there is a bug that attributes on constructors don't show up in generated .di files if they're on the right. I think that the real problem with putting them all on the right is that attributes such as static, public, and private are on the left in other languages, so it would be really weird to require that they be on the right. Still, it might be worth it.
Can't one have only the type qualifiers on the right? I mean it's only confusing for those. pure/nothrow int foo(); causes no confusion at all. The access qualifiers also work fine in the beginning. On the right they won't even compile.
I'm surprised that they don't work on the right. The argument for allowing const on the left-hand side has always been consistency - that all function attributes work the same. If that's not the case, then it seems to me like a definite argument for disallowing const on the left.
I do not know what are you referring to when you say function attributes. I distinguish the following: type qualifiers: const, immutable, maybe also inout function attributes: pure, nothrow storage class: ref, in, out, static access qualifiers: private, package, protected, public, export Storage class and access qualifies should go left only in my opinion and that's how dmd behaves. Function attributes can go left and right and I think there is nothing wrong with allowing that because there is no confusion. Even though I like them to be right as well. But this is matter of style. There is only confusion for type qualifies. Namely does the qualifier apply to the return type or the function (better said the type of this). Now it is consistent in the sense that const: int foo(); const { int foo(); } const int foo(); all mean the same. And Walter seems to be unsure whether forbidding const void foo() is worth the trouble, isn't it? I see and felt the pain for newcomers to decipher the meaning of const void foo(); I see two options: Either we clarify the documentation (e.g. examples) to help newcomers or we fix it in the front end. Picking the second option means to provide a patch and send it to review. Picking the first option means improving http://www.digitalmars.com/d/2.0/const3.html
Anything that modifies a function could be considered a function attribute: public, static, nothrow, pure, property, const, etc. Something that modifies the return value of a function or a function parameter isn't a function attribute. In the past, Walter's argument for const working as it is is that it is consistent with the other function attributes and that requiring that it be on the right would be inconsistent. - Jonathan M Davis
Jan 25 2011
prev sibling next sibling parent reply Jens Mueller <jens.k.mueller gmx.de> writes:
Jonathan M Davis wrote:
 On Tuesday 25 January 2011 01:45:49 Jens Mueller wrote:
 
 I do not know what are you referring to when you say function attributes.
 I distinguish the following:
 type qualifiers: const, immutable, maybe also inout
 function attributes: pure, nothrow
 storage class: ref, in, out, static
 access qualifiers: private, package, protected, public, export
 
 Storage class and access qualifies should go left only in my opinion and
 that's how dmd behaves.
 Function attributes can go left and right and I think there is nothing
 wrong with allowing that because there is no confusion. Even though I
 like them to be right as well. But this is matter of style.
 There is only confusion for type qualifies. Namely does the qualifier
 apply to the return type or the function (better said the type of this).
 Now it is consistent in the sense that
 const:
     int foo();
 const {
     int foo();
 }
 const int foo();
 
 all mean the same. And Walter seems to be unsure whether forbidding
 const void foo() is worth the trouble, isn't it?
 I see and felt the pain for newcomers to decipher the meaning of
 const void foo();
 I see two options:
 Either we clarify the documentation (e.g. examples) to help newcomers or
 we fix it in the front end. Picking the second option means to provide a
 patch and send it to review. Picking the first option means improving
 http://www.digitalmars.com/d/2.0/const3.html
Anything that modifies a function could be considered a function attribute: public, static, nothrow, pure, property, const, etc. Something that modifies the return value of a function or a function parameter isn't a function attribute.
You want to make a distinction regarding the modification. Those ones are called function attributes because they change a function in that regard. I'm not sure whether this clarifies things. I just think const/immutable as type qualifiers and you can apply those to member functions because the type of this object can be qualified as const/immutable.
 In the past, Walter's argument for const working as it is is that it is 
 consistent with the other function attributes and that requiring that it be on 
 the right would be inconsistent.
I didn't have that impression reading the mentioned bug reports. It seems there is more that I'm missing. Jens
Jan 25 2011
parent reply bearophile <bearophileHUGS lycos.com> writes:
Jens Mueller:

 I didn't have that impression reading the mentioned bug reports. It
 seems there is more that I'm missing.
See Walter answers here: http://d.puremagic.com/issues/show_bug.cgi?id=4070 Bye, bearophile
Jan 25 2011
parent Jens Mueller <jens.k.mueller gmx.de> writes:
bearophile wrote:
 Jens Mueller:
 
 I didn't have that impression reading the mentioned bug reports. It
 seems there is more that I'm missing.
See Walter answers here: http://d.puremagic.com/issues/show_bug.cgi?id=4070
I'm not getting it. In comment 1 Walter refers to const:, const {} and const (let's say inline) and they are all consistent (all are written left). That's his point. And forcing now const for the last syntax to be on the right makes it inconsistent. So he weighs consistency against the possible confusion and favors consistency in the end. That is a valid point. I do not see Walter arguing for consistency with non-type qualifiers. Meaning Walter's argument is valid but most of us weigh things here differently. Most favor inconsistency over possible confusion in this case. That's why the problem is currently solved as a matter of good style. I'd love to see that change but I think it's unfair to force it on Walter. Because he is not convinced yet. Next step is either propose a patch (i.e. trying harder to convince Walter, hoping that a patch may change things for him.) or document a preferred style in this regard clarifying the confusion. Jens
Jan 25 2011
prev sibling parent spir <denis.spir gmail.com> writes:
On 01/25/2011 10:45 AM, Jens Mueller wrote:
 I distinguish the following:
 type qualifiers: const, immutable, maybe also inout
 function attributes: pure, nothrow
 storage class: ref, in, out, static
 access qualifiers: private, package, protected, public, export
Nice & clear classification. Then, if you allow replacing "attribute" and "class" by "qualifier" (which by the way both are somewhat confusing because of other common meanings), you get a super-class of qualifiers. All are put aside a name which can denote a plain var, a type etc... Only in case of function they can be prefixed to the whole signature, which creates ambiguity with the return type: const int square (int x) {...} // func or return type? The obvious consistent choice, imo, would be to place them aside the function name: int const square (int x) {...} const int square (int x) {...} const int const square (int x) {...} but indeed would be a syntactic revolution ;-) Another solution would be to enforce parentheses except in the case of function: const int square (int x) {...} // func const(int) square (int x) {...} // return type Denis -- _________________ vita es estrany spir.wikidot.com
Jan 25 2011
prev sibling next sibling parent reply foobar <foo bar.com> writes:
Don Wrote:

 Steven Schveighoffer wrote:
 On Mon, 24 Jan 2011 13:36:36 -0500, bearophile 
 <bearophileHUGS lycos.com> wrote:
 
 There are six, seven or more people that wish to do something about 
 this situation. TDPL is the D2 reference, but few little changes over 
 its first edition are acceptable if they improve the D language a little.

 - Trass3r: asks if the code is ambiguous
 - Jonathan M Davis: does't like it and puts const/etc on the right
 - Simen kjaeraas thinks it's ambiguous though, and should be 
 disallowed, or at very least, discouraged.
 - Jens Mueller: Preferred style is to write const on the right
 - Andrej Mitrovic suggests to use   but says it clutters up source code.
 - I agree with Jonathan M Davis.

 What other people think about this situation? Do you want 
 const/immutable to be required on the right, or do you prefer the 
 current situation, or do you prefer some other solution?
I wouldn't say that I *prefer* the current solution, but the current solution is not so bad that I need it changed. It works fine, despite being confusing. If it wasn't consistent with the rest of the attributes, I'd say it was in need of changes, but it fits within the scheme already outlined.
It's a problem for all of the other attributes as well. I wish it were disallowed for all of them. Incidentally, putting it afterward always works. Putting it before doesn't always work, due to compiler bugs (for example, prefix 'pure' doesn't work for inner functions).
This "problem" happens because D belongs to the C-family of languages which puts the return type _before_ the function name. Languages that don't follow this syntactic convention (some would call it a mistake) have it very consistent and readable: attribute funcName inputParams -> outputParams { body } This is the typical functional language design. Of course I'm not suggesting to apply such a huge change to D but if I were to design a brand new language than I would put the return type at the end. I feel that putting function attributes at the end increases this IMHO bad design which boils down to a right-to-left programming language. I'm a native Hebrew speaker and it looks weird to me, so I can't imagine how it could look right to any left-to-right language native speaker...
Jan 24 2011
next sibling parent reply so <so so.do> writes:
 This "problem" happens because D belongs to the C-family of languages  
 which puts the return type _before_ the function name.
It has nothing to do with being a C-family language. C/C++ don't have this, and the rules are perfectly clear. It is just unifying two or more unrelated things in one syntax for the sake of consistency (and compiler complexity?).
Jan 24 2011
parent reply foobar <foo bar.com> writes:
so Wrote:

 This "problem" happens because D belongs to the C-family of languages  
 which puts the return type _before_ the function name.
It has nothing to do with being a C-family language. C/C++ don't have this, and the rules are perfectly clear. It is just unifying two or more unrelated things in one syntax for the sake of consistency (and compiler complexity?).
C++ style aka Yoda style: 1. public double func(int input) const; 2. const double func(int input); 3. const double func(int input) const; VS. hypothetical left-to-right style: 1. public const func (int input) -> (double); 2. func (int input) -> (const double); 3. const func (int input) -> (const double); Which ordering makes for a more natural read?
Jan 24 2011
next sibling parent reply so <so so.do> writes:
 C++ style aka Yoda style:
 1. public double func(int input) const;
 2. const double func(int input);
 3. const double func(int input) const;

 VS.
 hypothetical left-to-right style:
 1. public const func (int input) -> (double);
 2.  func (int input) -> (const double);
 3. const func (int input) -> (const double);

 Which ordering makes for a more natural read?
For you or for me? :)
Jan 24 2011
parent reply foobar <foo bar.com> writes:
so Wrote:

 C++ style aka Yoda style:
 1. public double func(int input) const;
 2. const double func(int input);
 3. const double func(int input) const;

 VS.
 hypothetical left-to-right style:
 1. public const func (int input) -> (double);
 2.  func (int input) -> (const double);
 3. const func (int input) -> (const double);

 Which ordering makes for a more natural read?
For you or for me? :)
Look at this from a "It reads like English" prospective and not from a "I'm an experienced c++ programmer and therefore already used to this crap" perspective. In other words, if you were just starting to learn your first programming language, what would confuse you less?
Jan 24 2011
parent reply so <so so.do> writes:
 Look at this from a "It reads like English" prospective and not from a  
 "I'm an experienced c++ programmer and therefore already used to this  
 crap" perspective.
 In other words, if you were just starting to learn your first  
 programming language, what would confuse you less?
If i was starting to learn a language, everything would confuse me. I know C rules, i learned it with zero hostility to any other language, it is perfectly natural to me. Ok you said your natural language is not English, how is that you still speak it, could be because you just learned its basics? Which one is the Yoda now? Hebrew or English? Which one is natural? Or i should ask which one is natural for "you"?
Jan 24 2011
parent reply foobar <foo bar.com> writes:
so Wrote:

 Look at this from a "It reads like English" prospective and not from a  
 "I'm an experienced c++ programmer and therefore already used to this  
 crap" perspective.
 In other words, if you were just starting to learn your first  
 programming language, what would confuse you less?
If i was starting to learn a language, everything would confuse me. I know C rules, i learned it with zero hostility to any other language, it is perfectly natural to me. Ok you said your natural language is not English, how is that you still speak it, could be because you just learned its basics? Which one is the Yoda now? Hebrew or English? Which one is natural? Or i should ask which one is natural for "you"?
Boy you missed the point by about 2.5 light years.. All I said is that Since D is English based (terminology, etc) it would make sense to follow a more English like word ordering in order to make the learning curve less steep. It obviously doesn't apply to someone who's already ahead of the learning curse such as yourself. There are Hebrew (and many other languages..) based programming languages out there and analogously it would make sense to strive for a Hebrew look and feel for those as well. Your argument boils down to something like "Who needs cars? I'm riding my horse Johnny since childhood..Feels natural to me" This has no relevance to an objective comparison between a car and a horse.
Jan 25 2011
parent reply so <so so.do> writes:
 Boy you missed the point by about 2.5 light years..
This can go forever as long as one of us resist to simple reasoning and analogy, and the other one has the energy to continue.
 All I said is that Since D is English based (terminology, etc) it would  
 make sense to follow a more English like word ordering in order to make  
 the learning curve less steep.
We are not teaching PL to monkeys, though i am not sure if they would find this an issue. Math is another language and it is quite flexible, I don't see people that left to right oriented use "one add two equal three", while the others use "three equal one add two" and flaming the others. After you learn the damn rule (which is in the basics of any language), both equally natural.
 Your argument boils down to something like "Who needs cars? I'm riding
 my horse Johnny since childhood..Feels natural to me" This has no
 relevance to an objective comparison between a car and a horse.
No. And i can't get better than that so this discussion for me now pointless.
Jan 25 2011
parent reply foobar <foo bar.com> writes:
so Wrote:

 Boy you missed the point by about 2.5 light years..
This can go forever as long as one of us resist to simple reasoning and analogy, and the other one has the energy to continue.
 All I said is that Since D is English based (terminology, etc) it would  
 make sense to follow a more English like word ordering in order to make  
 the learning curve less steep.
We are not teaching PL to monkeys, though i am not sure if they would find this an issue. Math is another language and it is quite flexible, I don't see people that left to right oriented use "one add two equal three", while the others use "three equal one add two" and flaming the others. After you learn the damn rule (which is in the basics of any language), both equally natural.
 Your argument boils down to something like "Who needs cars? I'm riding
 my horse Johnny since childhood..Feels natural to me" This has no
 relevance to an objective comparison between a car and a horse.
No. And i can't get better than that so this discussion for me now pointless.
No one is flaming here, this is just an academic discussion and I'm sorry if you took offense. The subject of this discussion is the learning curve and *not* about teaching monkey to program. I'm simply stating that each language (programming or otherwise) has a learning curve which can be statistically measured for an average human being. Fact is that for the _same_ person it takes more time to learn C++ compared to other languages. So I'm *not* talking about how smart you need to be in order to learn C but rather how long will it take you to learn different programming languages and comparing _the_languages_ based on that metric. Math is actually a very good example: It takes many years to learn math (from first class to university) and therefore it has a very steep learning curve. Here's another perspective: A professor that teaches introduction to CS in first semester to students that never programmed before needs to choose a programing language. One of the criteria for choosing which language to use is of course the learning curve. I'm sure you know that not all universities choose c/c++ for this. In fact, I know of several universities that use scheme as that first programming language.
Jan 25 2011
parent reply so <so so.do> writes:
 Here's another perspective:
 A professor that teaches introduction to CS in first semester to  
 students that never programmed before needs to choose a programing  
 language. One of the criteria for choosing which language to use is of  
 course the learning curve.
 I'm sure you know that not all universities choose c/c++ for this. In  
 fact, I know of several universities that use scheme as that first  
 programming language.
C++ is complex, it is obvious why it is harder to learn. Other languages don't have this mostly because they are not as powerful (i don't think i need to explain this). And this is what i mean, the reason its complexity, not the building blocks we are talking about. (again, i don't believe this syntax has anything to do with C++ being complex).
Jan 25 2011
parent reply foobar <foo bar.com> writes:
so Wrote:

 Here's another perspective:
 A professor that teaches introduction to CS in first semester to  
 students that never programmed before needs to choose a programing  
 language. One of the criteria for choosing which language to use is of  
 course the learning curve.
 I'm sure you know that not all universities choose c/c++ for this. In  
 fact, I know of several universities that use scheme as that first  
 programming language.
C++ is complex, it is obvious why it is harder to learn. Other languages don't have this mostly because they are not as powerful (i don't think i need to explain this). And this is what i mean, the reason its complexity, not the building blocks we are talking about. (again, i don't believe this syntax has anything to do with C++ being complex).
C++ is indeed complex and one of the reasons is its syntax (believe it or not). There was even an academic project to re-syntax C++ with the exact same semantics. Of course it's not the only cause of complexity in C++ but it is definitely one of the main ones. C++'s complexity has nothing to do with it's "power". D is as powerful and is less complex to use which is why we are here and not on the C++ dev mailing list. for example, D's classes/structs are way better than equivalent c++ code.
Jan 25 2011
parent reply so <so so.do> writes:
 C++ is indeed complex and one of the reasons is its syntax (believe it  
 or not). There was even an academic project to re-syntax C++ with the  
 exact same semantics.
 Of course it's not the only cause of complexity in C++ but it is  
 definitely one of the main ones.
If that is the case, you are probably right, but still i can't quite grasp it.
 C++'s complexity has nothing to do with it's "power". D is as powerful  
 and is less complex to use which is why we are here and not on the C++  
 dev mailing list. for example, D's classes/structs are way better than  
 equivalent c++ code.
Well if you think the complexity has nothing to do with power, how can you use D as a counterexample? :)
Jan 25 2011
parent foobar <foo bar.com> writes:
so Wrote:

 C++ is indeed complex and one of the reasons is its syntax (believe it  
 or not). There was even an academic project to re-syntax C++ with the  
 exact same semantics.
 Of course it's not the only cause of complexity in C++ but it is  
 definitely one of the main ones.
If that is the case, you are probably right, but still i can't quite grasp it.
 C++'s complexity has nothing to do with it's "power". D is as powerful  
 and is less complex to use which is why we are here and not on the C++  
 dev mailing list. for example, D's classes/structs are way better than  
 equivalent c++ code.
Well if you think the complexity has nothing to do with power, how can you use D as a counterexample? :)
"power" is a very subjective and problematic measure. We're discussing Turing complete languages and nothing prevents me from implementing a compiler/interpreter from one language to another thus gaining its "power". What we really want to talk is ease of expressiveness. C++ is more complex than D which means its harder to express oneself in c++. The difference is not that you can express something in one language but not in another (Both are Turing complete) but rather the *difficulty* of expressing the same thing in both languages. That difficulty makes for a steeper learning curve.
Jan 25 2011
prev sibling parent reply so <so so.do> writes:
 C++ style aka Yoda style:
 1. public double func(int input) const;
Also, you can't do this in C++. Which was my point.
Jan 24 2011
parent so <so so.do> writes:
 Also, you can't do this in C++.
 Which was my point.
Argh, hate it that you can't edit posts, ignore the second line.
Jan 24 2011
prev sibling next sibling parent Torarin <torarind gmail.com> writes:
2011/1/24 foobar <foo bar.com>:
 This "problem" happens because D belongs to the C-family of languages which
puts the return type _before_ the function name.

 Languages that don't follow this syntactic convention (some would call it a
mistake) have it very consistent and readable:
 attribute funcName inputParams -> outputParams { body }
 This is the typical functional language design.
It is arguably more consistent to have the return type come first, as in variable declarations: int a = 4; int foo() { return 5; } Both "foo()" and "a" are now of type int. Torarin
Jan 24 2011
prev sibling parent reply bearophile <bearophileHUGS lycos.com> writes:
foobar:

 This "problem" happens because D belongs to the C-family of languages which
puts the return type _before_ the function name.
Of course C++ has everything :-) See the trailing-return-type feature of C++0x: http://en.wikipedia.org/wiki/C%2B%2B0x#Alternative_function_syntax http://stackoverflow.com/questions/4523617/omit-return-type-in-c0x Bye, bearophile
Jan 24 2011
next sibling parent foobar <foo bar.com> writes:
bearophile Wrote:

 foobar:
 
 This "problem" happens because D belongs to the C-family of languages which
puts the return type _before_ the function name.
Of course C++ has everything :-) See the trailing-return-type feature of C++0x: http://en.wikipedia.org/wiki/C%2B%2B0x#Alternative_function_syntax http://stackoverflow.com/questions/4523617/omit-return-type-in-c0x Bye, bearophile
Of course they added it, they also experienced similar problems with the current syntax since it is out of place in the reading order.
Jan 24 2011
prev sibling parent so <so so.do> writes:
 Of course C++ has everything :-) See the trailing-return-type feature of  
 C++0x:
 http://en.wikipedia.org/wiki/C%2B%2B0x#Alternative_function_syntax
 http://stackoverflow.com/questions/4523617/omit-return-type-in-c0x

 Bye,
 bearophile
Now i am completely lost, i can't see any connection at all!
Jan 24 2011
prev sibling parent reply Kagamin <spam here.lot> writes:
foobar Wrote:

 This "problem" happens because D belongs to the C-family of languages which
puts the return type _before_ the function name.
 
 Languages that don't follow this syntactic convention (some would call it a
mistake) have it very consistent and readable: 
 attribute funcName inputParams -> outputParams { body }
ReturnType funcAttributes funcName(params) { body } BTW the problem is in separation of function attributes from return type attributes. I'm afraid, your example doesn't solve it.
Jan 26 2011
parent reply spir <denis.spir gmail.com> writes:
On 01/26/2011 11:02 AM, Kagamin wrote:
 This "problem" happens because D belongs to the C-family of languages which
puts the return type_before_  the function name.
  Languages that don't follow this syntactic convention (some would call it a
mistake) have it very consistent and readable:
  attribute funcName inputParams ->  outputParams { body }
ReturnType funcAttributes funcName(params) { body }
So what?
 BTW the problem is in separation of function attributes from return type
attributes. I'm afraid, your example doesn't solve it.
??? what do you /actually/ mean? attribute funcName inputParams -> attribute outputParams { body } Denis -- _________________ vita es estrany spir.wikidot.com
Jan 26 2011
parent Kagamin <spam here.lot> writes:
spir Wrote:

  attribute funcName inputParams ->  outputParams { body }
ReturnType funcAttributes funcName(params) { body }
So what?
So there's no need for FP-style syntax to just disambiguate attribute placing.
 BTW the problem is in separation of function attributes from return type
attributes. I'm afraid, your example doesn't solve it.
??? what do you /actually/ mean? attribute funcName inputParams -> attribute outputParams { body }
Look at the return type attribute. Whether it's a function attribute or type constructor? Both come first.
Jan 26 2011