Boost logo

Boost :

From: Chris Uzdavinis (chris_at_[hidden])
Date: 2005-07-15 18:51:10


"Paul Mensonides" <pmenso57_at_[hidden]> writes:

> Which is fairly obvious in nearly all cases. For example:
>
> MACRO()
>
> int f(...) { ... }

To humans, yes. To editors, well, that's a hard problem.

>> It is a pain to keep having to go back through the code and
>> re-hand-indent certain lines after auto-indenting a whole file or a
>> region of it.
>
> Why would you need to auto-indent a whole file?

A whole file "or region of it". I often find myself performing work
on a range of lines. Sometimes I rename variables, they get too long,
and I have to split the lines. This can be automated via editor
macros. After a bunch of such changes, I re-indent the buffer to
clean it up, strip out trailing whitespace, and so on.

Sometimes you decide that a chunk of code needs to be moved/refactored
into its own function, and the indentation level is no longer
correct. So you re-indent the whole region with that new function.
If it happens to use MACRO() in it, now you have to go through it and
re-indent.

I can list numerous reasons I'd re-indent multiple lines at once. If
you're really interested in the rest let me know and I'll keep going.
:)

> The only good reason that I see is if some sort of code generator
> that doesn't cater to user readable (e.g. the preprocessor) produces
> a mass of code that needs reformatting. In that case, it only needs
> to be temporarily reformatted, and it doesn't matter if it isn't
> quite perfect.

I don't worry too much if the whole file is generated, since I
probably wouldn't be editing it anyway, but instead would be editing
the spec file that was used to generate it. Or perhaps I'd edit the
generator itself.

> In this case, it's in a statement list where you can have null
> statements, so it doesn't matter if you put it there or not--it
> doesn't effect the design of the macro.

Agreed. In some cases the macro can be written to where the trailing
user-provided semicolon is optional (in terms of resulting behavior
and semantics.)

[snip]

>> However, I'd call this a poorly designed macro because it's
>> misleading and error prone. My personal guidelines are:
>>
>> 1) when a macro is logically its own statement,
>
> I'm asserting that this is never the case. The "logically" part
> above is a testament to the prevailing viewpoint. It isn't
> logically (and definitely not physically) a statement.

By using the word "logically", I meant that "X becomes Y" can quite
reasonably be described as being Y. When you throw extra parenthesis
after it and do other things to change how the preprocessor expands
macros, then it blurs things up. But for the typical, standard usages
of macros, this indistinction is not a problem.

Then again, there are extremely few people who write macros anywhere
near as complicated or ambitious as you do. The simple macros are
easy to write correctly. I'm not talking about newbies who don't
understand double evaluation, etc., either. I'm talking about
competant programmers who don't use macros very often and when they
do, apply the KISS principle.

[snip]
>> then the user should
>> provide the semicolon to aide in readability. This makes it clear
>> that the macro is "done". Therefore, I'd write SOME_MACRO1 to have
>> the user provide the semicolon. This requires that the macro
>> actually be done and its effect doesn't spill into the following
>> code.
>
> No it doesn't. The semicolon means nothing to the preprocessor, and the macro
> can still effect the code that follows.

Ok, here I think we have a miscommunication by the ambiguities of
English. I apologise. I meant for antecedent to which "this requires
..." referred was the author of the macro. The macro author must
ensure that after the user-provided semicolon, the macro has no more
effect on subsequent code. ("This requires that the macro ACTUALLY be
done...") I certainly didn't mean that having the user provide a
trailing semicolon somehow forces the preprocessor to be done
expanding the macro.

>
>> 2) when a macro is intended to modify the code that follows it, then
>> it should not have visible trailing semicolons or they will mislead
>> the user. It should be obvious from indentation that the macro is
>> being applied as a prefix to the code that follows, rather than a
>> self-contained statement.
>
> A self-contained statement, BTW, would include the semicolon. Otherwise, I
> don't disagree with this part--mainly because putting the semicolon would be
> erroneous in nearly all cases.

Well, I'm glad to see we already are in half agreement. :)

>> It seems clear to me how the semicolon's presence
>> (or lack thereof) can confuse maintence programmers,
>
> Confuse maintenance programmers only if they have the flawed
> viewpoint that I've been ranting about for years now. Worst case
> scenario is that the maintenance programmer has to look up the
> documentation for the macro. Having to do that enough times can
> change the perspective enough that it isn't a problem anymore.

The typical problems:
A) What documentation?

B) Programmer apathy.

C) "Aren't we supposed to avoid macros anyway? Why effort to study
   them in such detail if I'm supposed to feel guilty for using them
   anyway?"

Clearly, writing the boost preprocessor library requires a much more
strict view of what's going on, and macro purity is a must. But
really, how many people in the world could even write the boost
preprocessor library? Heck, how many actually understand it?
Compared to the number of C++ programmers, the number is probably less
than 1%. In most cases, for the majority of programmers, such
strictness is unnecessary and adds very little, but does make code
look weird, especially after the editor has indented it incorrectly.

-- 
Chris

Boost list run by bdawes at acm.org, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk