I am convinced there is some kind of long-term drinking game going on in the C standards committee to see how many different uses they can come up with for the word "static".
They don't really have a choice, do they? If you want to add features you can either: 1) make a new reserve word, possibly breaking existing code 2) reuse a reserve word in a new context.
Or you can add context-sensitive keywords, which are keywords only where it’s syntactically valid and identifiers elsewhere. Those two contexts are almost always mutually exclusive, and it’s obvious which one you’re in. ActionScript 3, though absolutely not a good example of language design in general, has a good example of this. You can say:
Deleted my previous comment because it was wrong (I was saying that it didn't help with the names of subroutines). It appears you can even have subroutines named after keywords, but only as long as you put "&" in front of it when you call it:
sub while
{
print "It works!\n";
}
&while();
I guess it is still the case that you can break perl code by adding keywords, if it collides with a subroutine that is called with the "&" symbol. Seems most code doesn't use "&" though, but it's a relatively quick fix.
I believe the @ is used only by the obj-c keywords and not the ones from C. So it'll be something more like this
@autoreleasepool{
for (int index = 0; index < 100; index++){
int error = [MyObject performSelector:@selector(addCoolFilterToImage:)];
if (error) {
return 32;
}
}
}
It looks like a syntax error to me. You can add numbers in array index brackets so a plus sign already has meaning there. Considering that a[10+] is just one character off from a[10++], it seems to me that this is just a bug waiting to happen.
It would be a syntax error. . . unless you add syntax for it.
As far as it being a bug waiting to happen, C already has plenty of traps like that - '=' vs '==', '&' vs '&&', and so on.
In terms of grammatical clarity, I shouldn't think it would be any more confusing than any other operators that have both unary and binary versions. By my count C already has three of those: '-', '&', '*'. The latter two are even examples where the unary meaning and the binary meaning are wholly unrelated.
Besides, it's a way of using + that is already well-established in everyday idiom. And there are semantically-related uses for + that are already well-established in computer languages, too - the Kleene +, for example, should be familiar to everybody.
In terms of how it would work for the grammar I realize this would be somewhat of a departure since it's repurposing a symbol that's normally an operator to be used in a manner that would be more like a keyword according to C syntax. . . but I think that's a detail that should be much more interesting to standards committees than it is to people who primarily just use the language. And in terms of the human factor I submit that it's much more workable than taking a word from the English language and repurposing it to mean something that's more-or-less the opposite of what it means in English.
I never ever had problems with it in C. I actually had a problem with it in another language (might have been a BASIC) where = was contextual, so one could do "a = 10" and then somewhere down the line "if x = 5 then". I used == and couldn't figure out what was wrong for nearly 5 minutes (I think it was recognising (or not) as an unexpected token).
= and == should have different meanings.
I also like how JavaScript has ===, although it is a little superfluous.
The problem with the plus sign is that people have a natural assumption about what it means (that is, the addition). Changing that make things more confusing. At least, C programmer are used now to the fact that the static keyword can have strange and different meanings and another one is no big deal.
That looks nice, but I think it could be simply void bar(int myArray[10]), since C effectively ignores the number inside the first pair of brackets in a parameter list, they could have added some meaning to it. No need for another meaning for "static"
C reserves part of the namespace for the language or implementation, so they have a third way, which they've used for e.g. boolean types in C99. Make a new reserved word in the reserved namespace (either starting with __ or just _ followed by a capital letter) and then add a standard header to #define or typedef the unfriendly reserved word to something nicer for code that wants it.
Managed C++ was chock full of __keywords for .NET memory management - like Apple's ARC in the worst case, except there were no good cases. While it probably was a clean superset of C++, it was painfully hideous.
CLI/C++, by which Microsoft replaced Managed C++, added new operators and keywords without much regard for backwards compatibility (=without underscores).
The implication being that people value code readability over __backward __compatibility. I have no data on the popularity of Managed C++ vs CLI/C++ though. I was only a fanboy because CLI/C++ looks awesome and I generally enjoy Herb Sutter's work, but then got sucked into the Appleverse.
Just adding __ keywords is not the approach I described, though. I described adding __keywords, and adding a standard header that redefines them into non-underscore keywords. This avoids breaking old code (it won't include the header) while allowing new code to use nicer keywords, if it wishes.
Right - I was just trying to provide context :) If there is anything in the Managed C++ -> CLI/C++ transition that is better than the ISO C approach, it is maybe the contextual keywords in CLI/C++ - something that can't be achieved with #define.
(off topic) I'm sure that was true at some point, but the comment is out of date now. To my surprise, if you download the current bash source code from [1], it actually has a yacc grammar -- see parse.y. It's 6000 lines, but it would be less intelligible without yacc I'm sure.
Honestly, it might be Stockholm syndrome, but I don't find bash hard to parse at all. The only real problem I see is that people get in trouble when they try to nest quoting styles. But there's basically never any reason to do that. User-defined functions basically eliminate this (may not be POSIX compliant, but supported in all shells I know of),
I factor all my shell scripts into 2 to 10 line functions and they are super easy to maintain and are 5-10x shorter than any alternative.
User-defined functions basically eliminate this (may not be POSIX compliant, but supported in all shells I know of),
User-defined functions are part of POSIX, but the function keyword is not. This bit me when I was porting a script from bash to dash (worth the effort on slower devices, as dash is significantly faster loading).
On bash you could do something like this:
function foo()
{
echo "Foo"
}
In POSIX shell (and, thus, also bash) you do this:
That is a comment on the style of C that Bourne used in his shell implementation. He used the pre-processor to e.g. name { BEGIN, } END and do other Algol-isms.
Duff would apparently rather read C that was written in C.
It's not at all the same situation for C. C's grammar is very-well defined and not at all hard to parse.
C++, on the other hand, has a horribly complex grammar. It would be unfair to say that "nobody really knows what it is," given that it has been standardized. But I think you will find that many tweaks to your code are needed when going between different C++ compilers.
I think what a lot of commenters in this thread are missing is that while the concept of a highly context-sensitive grammar seems simple, the reality is not. And having such a grammar makes it virtually impossible to have good tools.
Before some pedant reminds me that C's grammar is also context-sensitive: yes, I know. But you can parse C with lexx and yacc anyway, whereas you have no hope of doing this in C++.
I meant more on the programmers side than the implementors side. [0] But that's probably a moot point anyway, as I understand it most C code is probably crap plagiarized from amateur tutorials.
[0]: Nobody would here be an obvious exaggeration, as evidenced by the above blog post.
I think you are getting mixed up. The grammar of C isn't complex. Unrelatedly, C does have a few lesser-known features, but remarkably few for a 40-year-old language.
I never got into C because of books like "Expert C Programming"[0], knowing they exist tells me that theres a ton of "gotchas", and life is too short for that if I'm not really crazy about it in the first place.
Then again, as far as actual grammars go, I've heard C++ is bad enough that the compilers are the standard, and that if you want to be "compliant" with real world C++ code you copy every feature [1] of GCC.
Almost every language has a book titled "Expert $LANGUAGE". If a language doesn't have one of those, it's probably either very new, or nobody actually uses it, or both.
C and C++ are good for doing low-level stuff. If you don't want to do low-level stuff, then you should not worry about them. But in that case, you might also want to avoid commenting about them :)
clang is copying gcc's features because most of them are good features, and standards bodies move slowly. This is kind of an odd thing to criticize C++ for, since a lot of newer languages don't even have a standard, but just a reference implementation. It's hard to criticize your neighbor for living in a tent when you live in a sleeping bag.
>Almost every language has a book titled "Expert $LANGUAGE". If a language doesn't have one of those, it's probably either very new, or nobody actually uses it, or both.
I said books. I got that vibe in general from the people I met who claimed to be C wizards. Incredibly offputting.
>C and C++ are good for doing low-level stuff. If you don't want to do low-level stuff, then you should not worry about them. But in that case, you might also want to avoid commenting about them :)
I was going to delete my original comment because reading it over it felt like a bad idea. (I don't like jumping into ignorance induced shitstorms.)[0][1]
>This is kind of an odd thing to criticize C++ for, since a lot of newer languages don't even have a standard, but just a reference implementation.
I should have put "features" in quotes. I was specifically using the definition in the old jargon file. [2] So what I really meant to say is that the compilers end up supporting each others bugs for compatibility reasons.
As for reference implementations, if the reference implementation is for all practical reasons the only implementation, then you don't need a standard.
[0]: The comments I got in response are interesting enough that I'm actually glad I didn't.
[1]: EDIT. My ignorance.
[2]: See footnote on the last post, I should have made that more clear or used different terminology.
There was an "I heard" in that original context. Back in the great grand parent post. I might be able to find some examples, but since I don't have one off hand I'd rather drop the conversation.
So that's what I'm going to do unless I suddenly get the urge to go running through clangs commit log.
Comments
I am convinced there is some kind of long-term drinking game going on in the C standards committee to see how many different uses they can come up with for the word "static".
They don't really have a choice, do they? If you want to add features you can either: 1) make a new reserve word, possibly breaking existing code 2) reuse a reserve word in a new context.
Or you can add context-sensitive keywords, which are keywords only where it’s syntactically valid and identifiers elsewhere. Those two contexts are almost always mutually exclusive, and it’s obvious which one you’re in. ActionScript 3, though absolutely not a good example of language design in general, has a good example of this. You can say:
But you can also say:C# is up to about 25 of them, and it works well as long as you can resist the temptation to do silly things like
(The @ thing, which tells the compiler, "This is an identifier and not a keyword", can help quite a bit in a pinch.)C++11 also has them: override and final.
So:
But: So, for example, this is legal:Larry Wall (author of Perl) used this as an argument for "sigils", that is, putting $/@/% in front of every variable.
http://stackoverflow.com/questions/1091634/why-do-perl-varia...
(I merely state this as fact and offer no judgement!)
Deleted my previous comment because it was wrong (I was saying that it didn't help with the names of subroutines). It appears you can even have subroutines named after keywords, but only as long as you put "&" in front of it when you call it:
I guess it is still the case that you can break perl code by adding keywords, if it collides with a subroutine that is called with the "&" symbol. Seems most code doesn't use "&" though, but it's a relatively quick fix.Calling a sub with & has a special meaning, it exposes the current argument list @_ to the called sub. That's why you don't see it in most code.
I did not know that. Interesting. However, it only works if you call the sub without parentheses like this: &foo
Calling it with parentheses like &foo() would make @_ empty inside of foo. (Or if you said &foo("whatever") it would pass that as @_ instead.)
produces: as the output, and produces: as the output. At any rate, back to the original topic: it still doesn't prevent new keywords from potentially colliding. Oh well.I prefer the objective-c method of putting @ in front of every keyword.
Well, I might be upset if this were true for all keywords.
I'm a bit dizzy looking at that code, let me sit down for a moment.I believe the @ is used only by the obj-c keywords and not the ones from C. So it'll be something more like this
Yeah, that was kind of my point.
One better choice that comes to mind:
That's not better. It's more confusing to see a symbol that's normally an operator than it is to see a keyword.
It's only confusing if you are a language parser. I doubt that anyone else would have any problem guessing what this means.
It looks like a syntax error to me. You can add numbers in array index brackets so a plus sign already has meaning there. Considering that a[10+] is just one character off from a[10++], it seems to me that this is just a bug waiting to happen.
It would be a syntax error. . . unless you add syntax for it.
As far as it being a bug waiting to happen, C already has plenty of traps like that - '=' vs '==', '&' vs '&&', and so on.
In terms of grammatical clarity, I shouldn't think it would be any more confusing than any other operators that have both unary and binary versions. By my count C already has three of those: '-', '&', '*'. The latter two are even examples where the unary meaning and the binary meaning are wholly unrelated.
Besides, it's a way of using + that is already well-established in everyday idiom. And there are semantically-related uses for + that are already well-established in computer languages, too - the Kleene +, for example, should be familiar to everybody.
In terms of how it would work for the grammar I realize this would be somewhat of a departure since it's repurposing a symbol that's normally an operator to be used in a manner that would be more like a keyword according to C syntax. . . but I think that's a detail that should be much more interesting to standards committees than it is to people who primarily just use the language. And in terms of the human factor I submit that it's much more workable than taking a word from the English language and repurposing it to mean something that's more-or-less the opposite of what it means in English.
"As far as it being a bug waiting to happen, C already has plenty of traps like that - '=' vs '==', '&' vs '&&', and so on."
And C programmers are already spending plenty of their time cursing the world because of those things. Let's not add more of that, shall we? ;)
I never ever had problems with it in C. I actually had a problem with it in another language (might have been a BASIC) where = was contextual, so one could do "a = 10" and then somewhere down the line "if x = 5 then". I used == and couldn't figure out what was wrong for nearly 5 minutes (I think it was recognising (or not) as an unexpected token).
= and == should have different meanings.
I also like how JavaScript has ===, although it is a little superfluous.
Interestingly PostgreSQL's pl/pgsql does that.
There are two operators, equality = and assignment :=
But where it is clear that assignment was meant, = is treated as assignment. this means you can:
Interestingly this is entirely a Postgres-ism. Oracle's PL/SQL offers no such "feature."The problem with the plus sign is that people have a natural assumption about what it means (that is, the addition). Changing that make things more confusing. At least, C programmer are used now to the fact that the static keyword can have strange and different meanings and another one is no big deal.
That looks nice, but I think it could be simply void bar(int myArray[10]), since C effectively ignores the number inside the first pair of brackets in a parameter list, they could have added some meaning to it. No need for another meaning for "static"
C reserves part of the namespace for the language or implementation, so they have a third way, which they've used for e.g. boolean types in C99. Make a new reserved word in the reserved namespace (either starting with __ or just _ followed by a capital letter) and then add a standard header to #define or typedef the unfriendly reserved word to something nicer for code that wants it.
Observe the differences between Managed C++ and C++/CLI to see how poorly this approach works in practice.
Knowing nothing about either, can you elaborate?
Managed C++ was chock full of __keywords for .NET memory management - like Apple's ARC in the worst case, except there were no good cases. While it probably was a clean superset of C++, it was painfully hideous.
CLI/C++, by which Microsoft replaced Managed C++, added new operators and keywords without much regard for backwards compatibility (=without underscores).
The implication being that people value code readability over __backward __compatibility. I have no data on the popularity of Managed C++ vs CLI/C++ though. I was only a fanboy because CLI/C++ looks awesome and I generally enjoy Herb Sutter's work, but then got sucked into the Appleverse.
Just adding __ keywords is not the approach I described, though. I described adding __keywords, and adding a standard header that redefines them into non-underscore keywords. This avoids breaking old code (it won't include the header) while allowing new code to use nicer keywords, if it wishes.
Right - I was just trying to provide context :) If there is anything in the Managed C++ -> CLI/C++ transition that is better than the ISO C approach, it is maybe the contextual keywords in CLI/C++ - something that can't be achieved with #define.
With bonus points for uses that have absolutely nothing to do with the word's common meaning.
"Nobody really knows what the Bourne shell's grammar is. Even examination of the source code is little help."
— Tom Duff
Not exactly the same situation, considering that compilers work.
(off topic) I'm sure that was true at some point, but the comment is out of date now. To my surprise, if you download the current bash source code from [1], it actually has a yacc grammar -- see parse.y. It's 6000 lines, but it would be less intelligible without yacc I'm sure.
Honestly, it might be Stockholm syndrome, but I don't find bash hard to parse at all. The only real problem I see is that people get in trouble when they try to nest quoting styles. But there's basically never any reason to do that. User-defined functions basically eliminate this (may not be POSIX compliant, but supported in all shells I know of),
I factor all my shell scripts into 2 to 10 line functions and they are super easy to maintain and are 5-10x shorter than any alternative.
[1] http://tiswww.case.edu/php/chet/bash/bashtop.html
User-defined functions basically eliminate this (may not be POSIX compliant, but supported in all shells I know of),
User-defined functions are part of POSIX, but the function keyword is not. This bit me when I was porting a script from bash to dash (worth the effort on slower devices, as dash is significantly faster loading).
On bash you could do something like this:
In POSIX shell (and, thus, also bash) you do this: Reference: https://wiki.ubuntu.com/DashAsBinSh#functionbash is not the Bourne shell - it's the Bourne Again shell. sh is the Bourne shell.
That is a comment on the style of C that Bourne used in his shell implementation. He used the pre-processor to e.g. name { BEGIN, } END and do other Algol-isms.
Duff would apparently rather read C that was written in C.
It's not at all the same situation for C. C's grammar is very-well defined and not at all hard to parse.
C++, on the other hand, has a horribly complex grammar. It would be unfair to say that "nobody really knows what it is," given that it has been standardized. But I think you will find that many tweaks to your code are needed when going between different C++ compilers.
I think what a lot of commenters in this thread are missing is that while the concept of a highly context-sensitive grammar seems simple, the reality is not. And having such a grammar makes it virtually impossible to have good tools.
Before some pedant reminds me that C's grammar is also context-sensitive: yes, I know. But you can parse C with lexx and yacc anyway, whereas you have no hope of doing this in C++.
I meant more on the programmers side than the implementors side. [0] But that's probably a moot point anyway, as I understand it most C code is probably crap plagiarized from amateur tutorials.
[0]: Nobody would here be an obvious exaggeration, as evidenced by the above blog post.
I think you are getting mixed up. The grammar of C isn't complex. Unrelatedly, C does have a few lesser-known features, but remarkably few for a 40-year-old language.
I never got into C because of books like "Expert C Programming"[0], knowing they exist tells me that theres a ton of "gotchas", and life is too short for that if I'm not really crazy about it in the first place.
Then again, as far as actual grammars go, I've heard C++ is bad enough that the compilers are the standard, and that if you want to be "compliant" with real world C++ code you copy every feature [1] of GCC.
[0]: http://www.amazon.com/Expert-Programming-Peter-van-Linden/dp...
[1]: ftp://ftp.trailing-edge.com/pub/rsx11freewarev2/rsx81b/374001/jargon.txt
Almost every language has a book titled "Expert $LANGUAGE". If a language doesn't have one of those, it's probably either very new, or nobody actually uses it, or both.
C and C++ are good for doing low-level stuff. If you don't want to do low-level stuff, then you should not worry about them. But in that case, you might also want to avoid commenting about them :)
clang is copying gcc's features because most of them are good features, and standards bodies move slowly. This is kind of an odd thing to criticize C++ for, since a lot of newer languages don't even have a standard, but just a reference implementation. It's hard to criticize your neighbor for living in a tent when you live in a sleeping bag.
>Almost every language has a book titled "Expert $LANGUAGE". If a language doesn't have one of those, it's probably either very new, or nobody actually uses it, or both.
I said books. I got that vibe in general from the people I met who claimed to be C wizards. Incredibly offputting.
>C and C++ are good for doing low-level stuff. If you don't want to do low-level stuff, then you should not worry about them. But in that case, you might also want to avoid commenting about them :)
I was going to delete my original comment because reading it over it felt like a bad idea. (I don't like jumping into ignorance induced shitstorms.)[0][1]
>This is kind of an odd thing to criticize C++ for, since a lot of newer languages don't even have a standard, but just a reference implementation.
I should have put "features" in quotes. I was specifically using the definition in the old jargon file. [2] So what I really meant to say is that the compilers end up supporting each others bugs for compatibility reasons.
As for reference implementations, if the reference implementation is for all practical reasons the only implementation, then you don't need a standard.
[0]: The comments I got in response are interesting enough that I'm actually glad I didn't.
[1]: EDIT. My ignorance.
[2]: See footnote on the last post, I should have made that more clear or used different terminology.
So what I really meant to say is that the compilers end up supporting each others bugs for compatibility reasons.
Example?
There was an "I heard" in that original context. Back in the great grand parent post. I might be able to find some examples, but since I don't have one off hand I'd rather drop the conversation.
So that's what I'm going to do unless I suddenly get the urge to go running through clangs commit log.
Hooray for forward compatibility. "static" means "Semantic Token Always Taken In Context."
Today i learned what s.t.a.t.i.c. stands for.