
-----Original Message----- From: boost-bounces@lists.boost.org [mailto:boost-bounces@lists.boost.org] On Behalf Of David Abrahams
...which is no different than any other syntactic error that one might make when typing, and is usually the easiest kind of error to fix.
It is different in that many compilers won't detect it.
But it is a triviality. I understand the problem, but I fail to see how the problem is anything but slight, especially given the cirumstances where it could become significant. In those circumstances, the likelihood of this being the showstopper is extremely low.
The intentionally strong language is about people that habitually expect that semicolons after macro invocations at namespace scope are supposed to be there.
Well, some part of my brain obviously expects that habitually.
Then you're perspective needs to change so that it doesn't. I except that you in particular don't have any serious problems with the issues that I'm harping on, but that's probably because of your familiarity with preprocessor metaprogramming. This isn't about preprocessor metaprogramming per se, but about macros in general (obviously, any macro is a metaprogramming construct, but I think that you understand the distinction that I'm making).
One which I don't think we should accommodate. Worst case scenario is that someone makes the mistake and it has to be trivially fixed in a port. Fixing a "semicolon not allowed here" error is hardly difficult.
It depends whether you're the person at liberty to change the code.
...and you can't get those that are to fix it--which means that you're attempting to use source code on a compiler that it hasn't been tested on without the ability to modify it at all.
I'm just trying to say that modifying the code is much easier for some people than for others. If you're the author, it's usually trivial, but all sorts of restrictions get in the way for other people, to varying degrees.
I know, but you're projecting this problem into a circumstance where there are so many potential problems that the likelihood of this being the one thing that prevents reuse is extremely low. That circumstance (to reiterate) is attempting to use source code on a compiler that the code hasn't been tested on without the ability to modify it in any way.
It sounds like you're saying:
- Some naive users think macros are the same as functions
I'm saying that *most* users, naive or otherwise, view (for example) a 'max' macro as returning the greater of two (or more, I suppose) arguments.
I see where you're coming from.
To try to be a little more clear, "...as returning, for all intensive purposes, the greater of two arguments." That is, not confusing it with a function, but confusing a syntactic effect with a semantic one.
- That causes them to make mistakes
Indeed, except with what I said.
Huh?
Confusing syntactic effect with semantic effect causes mistakes.
- Thererefore we should design all macros to forbid a trailing semicolon in order to discourage that misconception
No, we should design macros without this being relevant. Generally speaking, we should define them to be self-contained entities that produce self-contained syntactic constructs.
Okay, that's a more refined point-of-view.
I'm definitely not saying that we should intentionally design macros to *not* look like functions. I'm saying that we should not intentionally design macros *to* look like functions.
I'm not referring to someone that is so naive that he doesn't know the difference between a macro and a function. I'm referring to typical C++ programmers, including just about everyone involved in this conversion, that thinks that making macros look like underlying language syntax is a valid goal.
I understand you to have two objections to that point of view, which can be summarized as
- It leads some people to think that max(a,b) is a function call
Not a function call, a semantic effect.
- it is self-perpetuating.
I understand the first objection, but to buy into the 2nd one I have to accept that it's an invalid goal before I can believe the reasons you give for it being invalid. So far that looks like a leap of faith.
It is an invalid goal because it intentionally blurs the distinction between syntactic and semantic effects. A lack of formal distinction leads to macro-related bugs that are the main reasons for the antipathy towards the preprocessor. I.e. it's unsafe, etc..
It causes errors far more insidious that extra semicolons.
What sort of insidious errors do you think I make because of that point of view?
Not you specifically, C and C++ programmers in general. One such mistake is multiple evaluation with side-effects (or even without them).
- How much easier it makes things when the macro requires the semicolon
How much easier does it make things? I'll that I've seen here is 1) editors don't indent properly because they can't handle it, and 2) extra semicolons aren't caught by some compilers making the code non-portable.
and 3) many people find it "more natural."
Which is the part that I most disagree with.
We have had reports in this thread that the semicolon sometimes comes up automatically, and not seeing the semicolon causes people some "cognitive dissonance."
Where "cognitive dissonance" means "having to view things from a superior and more technically correct perspective."
I'm not saying these are absolute non-factors, I'm saying that neither is a strong enough argument to violate (what should be) the principle and therefore propogate the same problems that we've had with the preprocessor for years and years.
Somehow I have trouble seeing a tiny design choice like this one as the cause of those problems.
It propogates the laudability of explicitly designing macros to look like syntactic entities. E.g. "Boost does it, therefore it must be good."
- That requiring the semicolon can keep a category of
errors from
creeping into code
Except that it isn't preventing some kind of insidious error. Instead, its a trivial error that is trivially fixed. I don't think that you can reasonably expect to use some source code with a compiler that it hasn't been tested on without having to change it at all. Extra semicolons are the least of your worries then.
Somehow, I do have that expectation though.
I seriously doubt any non-trivial piece of source code that contains no workarounds for a particular compiler and has not been tested on that compiler can be used "out-of-the-box" on that compiler--at least, not with C++. If we ever approximate the ideal of having portable C++ (meaning nearly all compilers approximate the standard very very closely) then this issue shouldn't come up because compilers would flag it as an error. Until that point, I don't think it's realistic to have that expectation.
Your own positions are rarely less than heavy-handed. This isn't a piddly little case of some silly misconceptions. It is a pervasive viewpoint that is flawed, which leads to errors, and which leads to broad denouncement of the preprocessor. It is an erroneous perspective, not a misunderstanding of the differences between macros and functions.
For my part, I think my priorities are exactly inverted from yours.
Then make another Boost policy.
Now _that_ would be heavy-handed :)
Yet we have some of those policies already. One example is tabs in source files. It is a total non-issue except in one situation: using tabs in the middle of a line of code rather than to indent it.
My priorities revolve around making things as pure as possible given the environments that we have to deal with. If that is divergent with Boost's priorities, then consider it the end of my affiliation with Boost.
Wow. I don't know what to say.
I don't know about the priorities of the rest of Boost, but I guess purity is a lower priority for me than some other things.
My conception of Boost, and the basis for my involvement (for whatever its worth), is that Boost isn't just about providing tools to get the job done. It's about providing tools--written the right way--to get the job done the right way to the greatest extent possible given the compilers and platforms that we have to deal with. If that isn't part of it, I have no interest in sticking around. Catering to editors in the face of purity is taking "compilers and platforms that we have to deal with" to the point of being asinine.
Convenience, usability, and the chance of not making a trivial unintentional error are important factors in the design of any component.
Convenience and usability from the point of view of other source code, not how that source code is written.
I _thought_ for a minute I understood what you meant by "from the point of view of other source code," but now I'm less sure. Seems to me "other source code" doesn't care about convenience and usability; only its author does.
From the point of view of other source code in terms of the source code complexity and size of a use of a construct.
Sorry, I don't understand yet.
It is certainly in terms of the convenience and usability of the author, but in terms of the complexity required for a use of a construct to be understood by the author and the terseness or verbosity of the expression of that construct by the author. Having no semicolon doesn't make it significantly less convenient nor does it increase complexity. Rather, it merely requires a programmer's perspective to be a little different--but not in a way that is difficult to grasp.
I see. Well, I still maintain that
#define MACRO struct xyz {
MACRO };
is a different category of beast.
Not from my perspective. In both cases, a standalone entity is started, but not finished--for no good reason. The only difference is that MACRO }; is obviously different from any normal C++ syntactic construct. If I *had* to choose between intentionally designing macros to not look like underlying syntactic constructs and intentionally designing macros to look like underlying syntactic constructs, I'd choose the former, but both a flawed constraints. Doing either, IMO, is bad design.
Except that in this case (the expression of a library feature), you're severly underestimating a sound principle by letting it be outweighed by the possibility of extra semicolons (which is quite possibly the easiest bug to fix of all time) and by automatic formatting of some editors that many people use (but many people don't).
Yeah, so far that's how the balance tilts for me. I understand your point of view better now, but still am not persuaded to raise my estimation of the importance of that principle.
The effect in this one particular instance is trivial. The effect of this being a generally agreed upon "best practice" is. This particular case is just one small addition to the mountain of bad code produced by the so-called "best practice".
The problem that I have is not so much with catering to editors (though I am against that in principle), but with catering to an incorrect viewpoint. The harm in doing so far outweighs extraneous issues like source code formatting over time.
If that was my motivation, I'd agree. But in fact requiring ^^^^^^^ This isn't a fact; it's your opinion. Most people that want to be able to add the semicolon (AFAICT) just think it's more syntactically pleasing.
Don't underestimate how much easier it gets for people to read and write code when it's syntactically pleasing.
If the preprocessor had more of an ability to manipulate syntax or was part of the syntax (as in Lisp or Scheme), then we could do this. But it doesn't, and all this does is make it look like the macro is something that it is not. Regards, Paul Mensonides