www.digitalmars.com         C & C++   DMDScript  

digitalmars.D - We need to kill C syntax for declaring function types

reply Don <nospam nospam.com> writes:
A great example of how C syntax is hurting us.
---
I found this bit of code in std.container, inside BinaryHeap:

     size_t insert(ElementType!Store value)
     {
         static if (is(_store.insertBack(value)))
         {
             ...
         }
         else ...

What does the static if do? It's *intended* to check if _store has a 
member function insertBack(), which accepts type of a 'value'.

But instead, it ALWAYS silently does the 'else' clause.
Unless _store.insertBack is a valid *type*, (eg, alias int insertBack;).
In which case it gives an error "declaration value is already defined".

Why?

This happens because
x(y); is valid C syntax for declaring a type 'y', such that &y is of 
type  'x function()'.

The C syntax is unspeakably ridiculous, useless, and downright 
dangerous. It shouldn't compile.

In the past, Walter has mentioned a weak argument for retaining C-style 
array declaration syntax, although I personally find it very 
unconvincing. But C's hideous function pointer syntax is on a whole 
other level. It's really hurting us. I believe it should be deprecated 
immediately. But the 'function type' syntax shouldn't be allowed even as 
a deprecated syntax. It's horrible.

Patch included in Bug 4987.
Oct 04 2010
next sibling parent reply bearophile <bearophileHUGS lycos.com> writes:
Don:

Thank you for bringing up this topic, Don :-)

In D, beside the C syntax for function types, there also is the C syntax for
function pointers. I presume it gives less problems than the first one.

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


 In the past, Walter has mentioned a weak argument for retaining C-style
 array declaration syntax, although I personally find it very
 unconvincing. But C's hideous function pointer syntax is on a whole
 other level. It's really hurting us. I believe it should be deprecated
 immediately. But the 'function type' syntax shouldn't be allowed even as
 a deprecated syntax. It's horrible.
One of the faults of C++, that increases its useless complexity a lot, is to have in many cases two ways (the C way and the C++ way) to do something. Generally the idea of duplicated syntax is bad. But I have translated lot of C code to D1 and I've seen that the possibility that D1 gives me to leave matrix definitions as they are helps me reduce the amount of changes to the C code needed to perform the translation (and I think this may help avoid some translation bugs, but I have no proof of this). So I leave declarations like: int mat[5][16]; And only later, when the D1 programs works correctly, I replace them by code like: int[16][5] mat; To merge such two needs, I have suggested a compilation switch, it may be named "-cstyle". It's designed to help translation of C code to D. If a module is compiled with -cstyle then DMD accepts C-style array declarations and C-style functions pointers, and it also gives warnings against passing by value large fixed-sized arrays and against the usage of global floating floating values before their initialization (those are two things that may trip a person that translates C code to D, because D passes fixed-sized arrays by value and doesn't initialize global floats to 0 but to NaN). The idea is, when you need to translate C code to D you use the -cstyle switch, that allows some C syntax and gives those two extra warnings. When your code works, you may finish the translation to D and stop using the -cstyle switch. See: http://d.puremagic.com/issues/show_bug.cgi?id=4580 What kind of error message does your patch gives for 4962? Bye, bearophile
Oct 04 2010
parent reply Don <nospam nospam.com> writes:
bearophile wrote:
 Don:
 
 Thank you for bringing up this topic, Don :-)
 
 In D, beside the C syntax for function types, there also is the C syntax for
function pointers. I presume it gives less problems than the first one.
Yes, I included that in the patch as well. It makes them deprecated, so they compile if and only if the -d command line switch is used.
 See also:
 http://d.puremagic.com/issues/show_bug.cgi?id=4530
 
 
 In the past, Walter has mentioned a weak argument for retaining C-style
 array declaration syntax, although I personally find it very
 unconvincing. But C's hideous function pointer syntax is on a whole
 other level. It's really hurting us. I believe it should be deprecated
 immediately. But the 'function type' syntax shouldn't be allowed even as
 a deprecated syntax. It's horrible.
One of the faults of C++, that increases its useless complexity a lot, is to have in many cases two ways (the C way and the C++ way) to do something. Generally the idea of duplicated syntax is bad. But I have translated lot of C code to D1 and I've seen that the possibility that D1 gives me to leave matrix definitions as they are helps me reduce the amount of changes to the C code needed to perform the translation (and I think this may help avoid some translation bugs, but I have no proof of this). So I leave declarations like: int mat[5][16]; And only later, when the D1 programs works correctly, I replace them by code like: int[16][5] mat; To merge such two needs, I have suggested a compilation switch, it may be named "-cstyle". It's designed to help translation of C code to D. If a module is compiled with -cstyle then DMD accepts C-style array declarations and C-style functions pointers, and it also gives warnings against passing by value large fixed-sized arrays and against the usage of global floating floating values before their initialization (those are two things that may trip a person that translates C code to D, because D passes fixed-sized arrays by value and doesn't initialize global floats to 0 but to NaN). The idea is, when you need to translate C code to D you use the -cstyle switch, that allows some C syntax and gives those two extra warnings. When your code works, you may finish the translation to D and stop using the -cstyle switch. See: http://d.puremagic.com/issues/show_bug.cgi?id=4580 What kind of error message does your patch gives for 4962?
bug.d(6): function declaration without return type. (Note that constructors are always named 'this') That is, it doesn't work out if it was intended to be a constructor, it gives the same error message for any function with no return type. Making a dedicated error message for constructors would require longer-range changes to the parser. But I believe that that the will happen.
Oct 04 2010
parent reply bearophile <bearophileHUGS lycos.com> writes:
Don:

 That is, it doesn't work out if it was intended to be a constructor, it
 gives the same error message for any function with no return type.
It seems this little patch of yours fixes something like 4 different bug reports present in Bugzilla :-) I suggest to add to the D docs a note that lists all the purposes of the -d command line switch, including accepting C function pointers. So the -cstyle command line switch may be replaced by the -d. Regarding bug 4580, is it possible to use the -d switch to deprecate (and re-enable when it is used) C-style array declarations too? (Bug 4580 talks about two extra warnings too, they too may be tied to the -d switch, but they are less important). Bye and thank you, bearophile
Oct 04 2010
parent reply Jesse Phillips <jessekphillips+D gmail.com> writes:
bearophile Wrote:

 Don:
 
 That is, it doesn't work out if it was intended to be a constructor, it
 gives the same error message for any function with no return type.
It seems this little patch of yours fixes something like 4 different bug reports present in Bugzilla :-) I suggest to add to the D docs a note that lists all the purposes of the -d command line switch, including accepting C function pointers. So the -cstyle command line switch may be replaced by the -d. Regarding bug 4580, is it possible to use the -d switch to deprecate (and re-enable when it is used) C-style array declarations too? (Bug 4580 talks about two extra warnings too, they too may be tied to the -d switch, but they are less important). Bye and thank you, bearophile
I still think it is important to resolve bugs related to C syntax, if you can still compile it. Is any tested done against deprecated features? While they shouldn't be used, it should still be checked that they work while they exist.
Oct 04 2010
parent reply bearophile <bearophileHUGS lycos.com> writes:
Jesse Phillips:

 Is any tested done against deprecated features?
Keep in mind that so far the main purpose of the -d in DMD2 was (I think) to enable Phobos code marked with "deprecated". Bye, bearophile
Oct 04 2010
parent reply Jesse Phillips <jessekphillips+D gmail.com> writes:
bearophile Wrote:

 Jesse Phillips:
 
 Is any tested done against deprecated features?
Keep in mind that so far the main purpose of the -d in DMD2 was (I think) to enable Phobos code marked with "deprecated". Bye, bearophile
Yes, and I think that if the code still exists and can be compiled then it should still be tested. I would agree that adding tests, or fixing bugs, isn't really a good idea, but it would be a good idea to keep existing tests and test with the -d option (that is new functionality isn't broken with -d enabled either).
Oct 04 2010
parent Don <nospam nospam.com> writes:
Jesse Phillips wrote:
 bearophile Wrote:
 
 Jesse Phillips:

 Is any tested done against deprecated features?
Keep in mind that so far the main purpose of the -d in DMD2 was (I think) to enable Phobos code marked with "deprecated". Bye, bearophile
Yes, and I think that if the code still exists and can be compiled then it should still be tested. I would agree that adding tests, or fixing bugs, isn't really a good idea, but it would be a good idea to keep existing tests and test with the -d option (that is new functionality isn't broken with -d enabled either).
Don't worry, that happens.
Oct 04 2010
prev sibling next sibling parent reply "Steven Schveighoffer" <schveiguy yahoo.com> writes:
On Mon, 04 Oct 2010 05:07:07 -0400, Don <nospam nospam.com> wrote:

 A great example of how C syntax is hurting us.
 ---
 I found this bit of code in std.container, inside BinaryHeap:

      size_t insert(ElementType!Store value)
      {
          static if (is(_store.insertBack(value)))
          {
              ...
          }
          else ...

 What does the static if do? It's *intended* to check if _store has a  
 member function insertBack(), which accepts type of a 'value'.

 But instead, it ALWAYS silently does the 'else' clause.
 Unless _store.insertBack is a valid *type*, (eg, alias int insertBack;).
 In which case it gives an error "declaration value is already defined".
I'm really confused here. I could have sworn I've seen compile time checks like this everywhere. Is the "bug" that's unflagged by the compiler that you are missing a typeof(...)?
 Why?

 This happens because
 x(y); is valid C syntax for declaring a type 'y', such that &y is of  
 type  'x function()'.
Wait, I thought when declaring a function pointer, you had to have the (*) in there? Plus I thought you had to have an extra set of parentheses? I've never seen this before. Trying... Oh, that's freaking awful. x(y); silently compiles into something useless, you need to declare it with a typedef in order to use it (and even then, it's horrible). It's like accepting the line int; Yes, 100% agree, get rid of this. Does that mean we need to get rid of C-style function pointer declarations? Because I recently saw a use for them (deciphering C-style function pointer syntax). Even if that has to go, I'm fine with it. -Steve
Oct 04 2010
parent reply Don <nospam nospam.com> writes:
Steven Schveighoffer wrote:
 On Mon, 04 Oct 2010 05:07:07 -0400, Don <nospam nospam.com> wrote:
 
 A great example of how C syntax is hurting us.
 ---
 I found this bit of code in std.container, inside BinaryHeap:

      size_t insert(ElementType!Store value)
      {
          static if (is(_store.insertBack(value)))
          {
              ...
          }
          else ...

 What does the static if do? It's *intended* to check if _store has a 
 member function insertBack(), which accepts type of a 'value'.

 But instead, it ALWAYS silently does the 'else' clause.
 Unless _store.insertBack is a valid *type*, (eg, alias int insertBack;).
 In which case it gives an error "declaration value is already defined".
I'm really confused here. I could have sworn I've seen compile time checks like this everywhere. Is the "bug" that's unflagged by the compiler that you are missing a typeof(...)?
Yes.
 Why?

 This happens because
 x(y); is valid C syntax for declaring a type 'y', such that &y is of 
 type  'x function()'.
Wait, I thought when declaring a function pointer, you had to have the (*) in there? Plus I thought you had to have an extra set of parentheses? I've never seen this before. Trying... Oh, that's freaking awful. x(y); silently compiles into something useless, you need to declare it with a typedef in order to use it (and even then, it's horrible). It's like accepting the line int; Yes, 100% agree, get rid of this. Does that mean we need to get rid of C-style function pointer declarations? Because I recently saw a use for them (deciphering C-style function pointer syntax).
I agree, I use it for the same thing. In the patch, I made C-style function pointers deprecated (so you can still compile it with the -d switch) and C-style abominable x(y) types illegal. I would expect that it always remains a deprecated syntax, to aid conversion of C-style code. But in my experience, you always want to get rid of them eventually.
Oct 04 2010
next sibling parent "Steven Schveighoffer" <schveiguy yahoo.com> writes:
On Mon, 04 Oct 2010 08:55:55 -0400, Don <nospam nospam.com> wrote:

 Steven Schveighoffer wrote:
  Yes, 100% agree, get rid of this.  Does that mean we need to get rid  
 of C-style function pointer declarations?  Because I recently saw a use  
 for them (deciphering C-style function pointer syntax).
I agree, I use it for the same thing. In the patch, I made C-style function pointers deprecated (so you can still compile it with the -d switch) and C-style abominable x(y) types illegal. I would expect that it always remains a deprecated syntax, to aid conversion of C-style code. But in my experience, you always want to get rid of them eventually.
Perfect solution, thanks! -Steve
Oct 04 2010
prev sibling parent BCS <none anon.com> writes:
Hello Don,

 Steven Schveighoffer wrote:
 
 On Mon, 04 Oct 2010 05:07:07 -0400, Don <nospam nospam.com> wrote:
 
 A great example of how C syntax is hurting us.
 ---
 I found this bit of code in std.container, inside BinaryHeap:
 size_t insert(ElementType!Store value)
 {
 static if (is(_store.insertBack(value)))
 {
 ...
 }
 else ...
 What does the static if do? It's *intended* to check if _store has a
 member function insertBack(), which accepts type of a 'value'.
 
 But instead, it ALWAYS silently does the 'else' clause.
 Unless _store.insertBack is a valid *type*, (eg, alias int
 insertBack;).
 In which case it gives an error "declaration value is already
 defined".
I'm really confused here. I could have sworn I've seen compile time checks like this everywhere. Is the "bug" that's unflagged by the compiler that you are missing a typeof(...)?
Yes.
 Why?
 
 This happens because
 x(y); is valid C syntax for declaring a type 'y', such that &y is of
 type  'x function()'.
Wait, I thought when declaring a function pointer, you had to have the (*) in there? Plus I thought you had to have an extra set of parentheses? I've never seen this before. Trying... Oh, that's freaking awful. x(y); silently compiles into something useless, you need to declare it with a typedef in order to use it (and even then, it's horrible). It's like accepting the line int; Yes, 100% agree, get rid of this. Does that mean we need to get rid of C-style function pointer declarations? Because I recently saw a use for them (deciphering C-style function pointer syntax).
I agree, I use it for the same thing. In the patch, I made C-style function pointers deprecated (so you can still compile it with the -d switch) and C-style abominable x(y) types illegal. I would expect that it always remains a deprecated syntax, to aid conversion of C-style code. But in my experience, you always want to get rid of them eventually.
I.e. the use of C-style function pointer syntax is deprecated, the syntax it self is not. Got it, nice. -- ... <IXOYE><
Oct 04 2010
prev sibling next sibling parent reply Marianne Gagnon <auria.mg gmail.com> writes:
Hi,

 
 The C syntax is unspeakably ridiculous, useless, and downright 
 dangerous. It shouldn't compile.
 
 In the past, Walter has mentioned a weak argument for retaining C-style 
 array declaration syntax, although I personally find it very 
 unconvincing. But C's hideous function pointer syntax is on a whole 
 other level. It's really hurting us. I believe it should be deprecated 
 immediately. But the 'function type' syntax shouldn't be allowed even as 
 a deprecated syntax. It's horrible.
 
 Patch included in Bug 4987.
I don't have much weight, but... seconded, definitely :) D needs to be as clean as possible, bad C syntax needs to go. -- Auria
Oct 04 2010
parent Andrei Alexandrescu <SeeWebsiteForEmail erdani.org> writes:
On 10/4/10 10:06 CDT, Marianne Gagnon wrote:
 Hi,

 The C syntax is unspeakably ridiculous, useless, and downright
 dangerous. It shouldn't compile.

 In the past, Walter has mentioned a weak argument for retaining C-style
 array declaration syntax, although I personally find it very
 unconvincing. But C's hideous function pointer syntax is on a whole
 other level. It's really hurting us. I believe it should be deprecated
 immediately. But the 'function type' syntax shouldn't be allowed even as
 a deprecated syntax. It's horrible.

 Patch included in Bug 4987.
I don't have much weight, but... seconded, definitely :) D needs to be as clean as possible, bad C syntax needs to go. -- Auria
Don's post was quoted on reddit: http://www.reddit.com/r/programming/comments/dm8n8/the_many_faces_of_d_slides_pdf/ Andrei
Oct 04 2010
prev sibling next sibling parent reply "Lars T. Kyllingstad" <public kyllingen.NOSPAMnet> writes:
On Mon, 04 Oct 2010 11:07:07 +0200, Don wrote:

 [...]
 
 The C syntax is unspeakably ridiculous, useless, and downright
 dangerous. It shouldn't compile.
 
 [...]
 
 Patch included in Bug 4987.
http://dsource.org/projects/dmd/changeset/703 :) -Lars
Oct 05 2010
parent reply Walter Bright <newshound2 digitalmars.com> writes:
Lars T. Kyllingstad wrote:
 http://dsource.org/projects/dmd/changeset/703
 
 :)
Don, as usual, made a compelling case.
Oct 05 2010
parent Bruno Medeiros <brunodomedeiros+spam com.gmail> writes:
On 05/10/2010 10:50, Walter Bright wrote:
 Lars T. Kyllingstad wrote:
 http://dsource.org/projects/dmd/changeset/703

 :)
Don, as usual, made a compelling case.
Programs going down in flames is always a compelling argument... ^_^' -- Bruno Medeiros - Software Engineer
Oct 26 2010
prev sibling parent Bruno Medeiros <brunodomedeiros+spam com.gmail> writes:
On 04/10/2010 10:07, Don wrote:
 A great example of how C syntax is hurting us.
 ---
 I found this bit of code in std.container, inside BinaryHeap:

 size_t insert(ElementType!Store value)
 {
 static if (is(_store.insertBack(value)))
 {
 ...
 }
 else ...

 What does the static if do? It's *intended* to check if _store has a
 member function insertBack(), which accepts type of a 'value'.

 But instead, it ALWAYS silently does the 'else' clause.
 Unless _store.insertBack is a valid *type*, (eg, alias int insertBack;).
 In which case it gives an error "declaration value is already defined".

 Why?

 This happens because
 x(y); is valid C syntax for declaring a type 'y', such that &y is of
 type 'x function()'.

 The C syntax is unspeakably ridiculous, useless, and downright
 dangerous. It shouldn't compile.
Whoa. I considered myself completely knowledgeable of the C language, but I had no idea about this syntax. (Note: by "completely knowledgeable" I don't mean I could recite the spec by memory, but rather that at least I knew what features, syntax and semantics ANSI C 89 had available.) Hum, your description of what "x(y);" means seems slightly incorrect though. Both in C and D, if x is a type, then it is the same as "x y;", that is, it declares a variable y with type x. If x is not a type but y is, it seems to be the same as "void x(y);", that is, it declares a function prototype named x. If both are not types, then it declares that strange thing I don't quite understand nor am I interested to... I do vaguely recall learning about the first scenario, where a variable is declared, but I had not idea about the others. Is this mentioned in K&R TCPL 2nd edition? Not that it matters, it's still horrid! I'm glad we're nuking it from D. -- Bruno Medeiros - Software Engineer
Oct 26 2010