Guys,
It isn't a matter of political correctness or programming style issue
which is subject to personal tastes and opinion but a matter of following the API specification.
(programming style != programming practices)
The API for digitalWrite() says HIGH and LOW. It does not say 1 or 0 or zero or non-zero.
To use anything other than HIGH and LOW or even depending on HIGH and LOW
being bit opposites of each other
is using using the API or the API defines in a way that is not specified or
guaranteed to work.
Grumpy Mike and GoForSmoke as far as your comments go, I actually am a hardware type.
(I actually do both)
I have worked on many embedded systems and led many development teams
over the past 30 years, some of which have been used in Aircraft.
I have also designed several ASICs,
some that were used in 10's of millions of DSL modems,
so yes I am quite familiar with hardware concepts and I'm no rookie
with respect to these concepts.
I have had to deal with bugs created by other developers that were doing
the very kinds of things done in some of the examples in this thread.
It is not fun to track down these type of bugs.
And while is very likely that LOW and HIGH will be logical opposites
(if LOW is 0) there are many examples like this one:
state = !state;
That make the assumption that LOW is 0 and HIGH is 1.
The reason for having an API is to isolate the application from the internal details
of an implementation. This not only has the potential to make the interface easier
to use and understand but also allows the the implementation to change in the future
to extend functionality while still providing full backward compatibility.
By using the API or its defines in ways that are not defined, you are taking
a risk by taking advantage of knowledge of the internal implementation which may change out
from under you in the future.
We had a very similar lengthy discussion on this very same topic a few months ago.
And I'll site the same hypothetical example I did then..
Lets suppose that Arduino advances to a chip that supports real analog output vs just PWM.
So now things have to change a bit to support PWM vs true analog ouput.
Now assume that it becomes desirable to extend the digitalWrite() function to
support PWM as well as simple HIGH/LOW.
IF people had followed digitalWrite() API by always using HIGH and LOW,
Then digitalWrite() could be made "smarter" or extended to support PWM, by simply changing the value of HIGH
from 1 to 255.
That way the existing dititalWrite(pin, val) API could still work since LOW would give you a solid low pin and HIGH would
give you solid high pin but values other than HIGH & LOW would give you a PWM signal on the pin.
Those people that always used HIGH and LOW would see no difference or any issues for setting pin outputs
to solid low or solid high while those that assumed that
HIGH was 1 or took advantage that digitalWrite() would set a pin high for any non zero value
(which is what digitalWrite() does today) would have their code break when using the newer implementation.
It is also theoretically possible that there could be another implementation that used
LOW and HIGH as negative values or maybe LOW is negative and HIGH is a number that is very large
to indicate something different for solid outputs vs a PWM output.
Even in that case those that used HIGH and LOW would still continue to work fine.
(Udo: All the examples that use exclusive ORing, would break if LOW was not 0)
While all hypothetical, this is an example of why using an API outside of its specification or taking
advantage of internal behaviors is bad programming practice. It has nothing to do with
political correctness or programming style, it has to do with using the API as it is defined vs taking advantage
of internal implementation details.
Whenever you take advantage of an API's internal implementation details, you run the risk
that should those implementation details ever change in the future you run the risk
that your code will break.
For a moment, ignore that we are specifically talking about digitalWrite() and the definitions
of HIGH and LOW.
Would you still advise someone to ignore an API definition and use calculated values or constants
rather than the actual defines when using API? Probabaly not.
The goal should be to help guide less knowledgeable people increase their technical & programming skills
and try to steer them in the direction of good programming practices that they can use
on going into the future.
Showing them "clever" code that takes advantage of internal implementation details
or, IMHO, somewhat sarcastic implementations like this:
cli();
state = state==HIGH ?LOW: state==LOW? HIGH: state;
sei();
are not helpful.
I think for less technical folks that are just starting out trying to understand basic
concepts, IMHO, it is best to give them clear,
simple easy to understand examples which avoid the use of ternary macros
and that strictly follow the APIs.
So I would recommended either the original code:
if (state == LOW)
{
state = HIGH;
}
else
{
state = LOW;
}
digitalWrite(pin, state);
delay(1000);
Or to save a bit of typing:
if (state == LOW)
state = HIGH;
else
state = LOW;
digitalWrite(pin, state);
delay(1000);
What most of you seem to be overlooking is the bigger concept and that is of using an API
the way it is defined vs taking advantage of the internal implementation details of the API
or its defines.
I've seen code examples out there that end up passing values other 0 or 1 to the DigitalWrite().
(they create other non-zero values and assume it works the same as HIGH)
While these work today, it is still very bad programming practice.
So I'll say it again, the best programming practice is to strictly stick to the API definition
and make no assumptions about the internal behaviors and values of the defines used the API.
That is the only way to ensure that your code can continue to work in the future
should the underlying mechanisms in the API change or be extended.
i.e. always use the defines from the API vs try to calculate them based on knowing what the define values are
or how they are used.
--- bill