I don't enjoy reading code where I see (for flipping a pin)
digitalWrite(! digitalRead(pin));
instead of
digitalWrite(digitalRead(pin) == LOW ? HIGH : LOW);
for example. The latter is respecting the documentation (HIGH and LOW are the two values accepted by digitalWrite or returned by digitalRead) and you don't depend on a bool to integral promotion and the magic number selected for HIGH and LOW.
I'm a strong believer that honouring types, not abusing implicit promotions and strong typing overall is good for code quality and maintainability.
I like that C++ is more stringent than C for this.
Now this goes totally off topic Why does it have to be digitalRead()digitalWrite() at all? Wouldn't it be easier to say D0 =! D0 ? .. that is, assuming (avr) you want to read PIN and not PORT or whatever pitfalls the simplification at library level has prepared for you. Why is HIGH/LOW better than true/false? Is it important to define 100 different versions of boolean? ... and down we go the religious road, so lets prepare pitch forks and lite the torches
If the definition of the API changes undocumented and the new implementation is incomplete 'cause it does not redefine operators for (in this case) PinStatus to behave like boolea before then that's not a fault of the language but the API designer. No typed language prohibits that type of error.
the doc always said use HIGH and LOW for digitalRead and digitalWrite. It never mentioned the type of these constants.
if you had written
digitalWrite(digitalRead(pin) == LOW ? HIGH : LOW);
you respected the documentation and you are fine
if you had written
digitalWrite(! digitalRead(pin));
you did not and you are in trouble.
My point is that if arduino had used strong typing initially instead of the #define for HIGH and LOW then the compiler would never have let developers get away with digitalWrite(! digitalRead(pin)); in the first place and so we would not have zillions of projects that fail.
Ok. Which projects "fail" because of treating digitalWrite's pinStatus as something other than boolean with HIGH==true and LOW==false? Which platforms do anything unexpected with non-boolean in digitalWrite()?
if arduino had used strong typing initially instead of the #define for HIGH and LOW then the compiler would never have let developers get away with digitalWrite(! digitalRead(pin));
Is that so? Seems to me that the newer chips (anything using "ArduinoAPI" carefully use an appropriate type for digitalWrite's arguments: void digitalWrite( pin_size_t ulPin, PinStatus ulVal ), where PinStatus is an enum, and yet builds work just fine with:
(and that last line doesn't do what you might expect.)
I mean, I get your point, but IMO digitalWrite()/etc is not a good example of where this would have been useful, and C/C++ doesn't seem to have the checking that you want.
It is more an example of a failure in API design and documentation than a cause for strong typing - the values should have been booleans and the documentation should have said that HIGH and LOW were synonyms for true and false. pinStatus is a travesty that never should have happened, or never been used for digitalRead/Write, anyway. attachInterrupt() needed a separate type...
In C++ you can go from an enum to its integral value but the opposite in not true and so a bool type variable evaluated to true (its own type in C++) won’t be promoted to int 1 which happens to be the matching value for HIGH in the enum.
That’s what happened when they à introduced the enum - see the GitHub
I still wonder why digitalRead/digitalWrite were used in the first place. And I do not see the reasoning behind pinStatus - IMO it's just a library layer to make things "easier" but in fact more complicated.
Breaking the API for no reason at all is a bad thing. But I think even in C++ this could have been handled transparently for the user (but complicated for the API developer)
Yes, and it avoids keeping local storage of the state of the variable. Convenient in some situations, though it's easily overused.
Sometimes, you just want to invert the bit, but other times you want to explicitly set it to 1 or 0. (cue the pedants, HIGH|LOW, true|false, etc. etc. etc.)
I would play the devil's advocate here and argue the other way. I see the failure on the other side of things. I think it would have been more useful for digitalRead and digitalWrite to use boolean arguments. What else will a digital pin be besides on or off, HIGH or LOW, true or false.
If anything needs to be fixed, I think the API should change to allow for this. It seems most natural.
That would have required more extensive use of C++ (you couldn't do it in C), the need to define a bunch of names that might conflict with likely used variables (unless you made the users define the pins they used, which would be unacceptable), interesting naming issues on more complex boards, and perhaps even more bloat than already exists.
(Also, can object member variables be put in PROGMEM?)
Why is HIGH/LOW better than true/false ?
Ugly as it may be, the whole Arduino pin-naming scheme is probably the biggest reason for Arduino success among its target user base (ie artists and such.) Concepts like ports, bitmasks, and booleans were too complex and confusing. "pins" were ok. At least, when they corresponded to clearly labeled things on a board.
Still harder especially for me with a very shaky left hand.
Using “1” just seems more natural to me as I am just learning C++ coming from using assembly and BASIC. I look at the ability to do things this way as a flexibility in the language. I just wonder if it will come back to bite me down the road.
I have been using a denounce library that defines everything as uint8_t. If there was ever a place to use Boolean that seems like the place.