@retrolefty
'rules' sometimes seem to be ... variable
The "rules" are not ambiguous. There are ISO language standards for C and C++. Not all compilers are completely compliant with all of the rules, but, in my experience, there are not very many exceptions as far as the preprocessor is concerned.
In particular, the preprocessor is part of the C and the C++ standard language specifications, and its use is defined therein. That is, there are certain, well-defined, rules about the various forms that #define directives can take and where they can occur in a program.
People's ideas of "good programming practices" sometimes add restrictions and conventions that may make things more readable and consistent to (some of) us mere humans, but the compiler never gets confused.
The driving philosophy of Arduino is to get people up to the point of doing some interesting things with their hardware without going through the agony (and ecstasy) of actually learning a lot of the details of C and C++. It works better for some people than others.
A valuable service of this forum is to let people ask questions and try to get meaningful help without just being told to go read a textbook.
Complicated function-like macros are the bane of anyone (that I have ever known) who has to maintain and debug OPC (Other People's Code).
On the other hand, lines like "#define buttonPin 2
" aren't too hard to understand and to use, but people who don't have a lot of experience can't understand why putting a semicolon at the end can (sometimes) create problems when a #define macro is used.
If people look at working examples and make simple changes (like changing the definition of buttonPin to something other than 2), they may be able to lead full, rich, rewarding lives without ever descending into the lowest levels of hell where the real #define macro wogs reside.
Bottom line:
That's why we need to see the actual code instead of having someone tell us that they tried "it" and "it" didn't work and they got an error message "along the lines of..." (This is true, no matter what "it" is.)
Regards,
Dave
Footnote:
The "best" advice, according to some "real" C++ applications programmers that I have known might be not to use #define lines at all, just use a const variable declarations or some such thing for simple macros and to use "inline" functions or, maybe, function templates instead of function-like macros.
However since the #define processor directive is well defined (and not absolutely obsolete) and since some people ask about them, I think that trying to give advice about them is not a disservice to beginners (or not-so-beginners). I do believe that making up a bunch of stuff that has no connection to the real "rules" of the language can be confusing in the abstract.