On 01/21/2016 10:32 AM, Nathan Scott wrote:
...
2. Sentinel values
I'm not so much against sentinels in the way Mark seemed to be, as
it looks kinda handy, but the choice of zero as a sentinel integer
value strikes me as questionable. [...prefer -1...]
OK, will look into that. [...]
A second thought appears here. We support unsigned integer types, for
whom a -1 sentinel becomes an inconveniently large number. The
sentinel-checking logic would have to be metric-type specific and IMHO
unsightly, whereas zero is OK everywhere.
metric-type specific sentinels will lead us into a bowl of spaghetti
Except for double/float. And Unsightly is trumped by Misleading.
Remember, the point of sentinel values is to be convenient for
computation & output, should the application *not care* about the
presence of errors. (If the application cared about errors, it would
use individual status integers.)
applications should *always* care about errors. my 2c :)
So what matters is not how easily
the sentinel can be identified, but rather how smoothly an *unchecked*
sentinel value would mesh in with real values, with minimal disruption
of application data flow.
Firstly, reporting incorrect information is a big problem. And zero
as a numeric value is so often of meaning & importance that no matter
how uncaring a tool author is about ENODATA, we cannot encourage it.
yep
Consider many values from the real world - swap.used, filesys.free,
mem.util.{free,dirty,...}, the many metrics that are indicate errors,
and on and on - zero really is the worst possible sentinel choice.
agree
Secondly, above rationale is the inconsistent with the approach taken
for double/float which generates NaN instead of 0.0. We need to pick
one or the other, not half-and-half, and its important to not provide
potentially-very-misleading zero values as defaults.
It makes most sense to me to have the sentinel values as: empty string,
NaN (as you have), and all-bits-set for integers (ie -1). Then perhaps
provide a helper to aid with this programmer inconvenience angle:
perhaps -2^31, which is kind of the same as a float NaN and better than zero
IMO :
/* Not An Integer */
#define NAI (int)(0.0F/0.0F)
#define NAI2 (int)(-1 << 31)
void main(void) { printf ("%d %d 0x%08x\n", NAI, NAI2, NAI2); }
# ./a.out
-2147483648 -2147483648 0x80000000
Since we're dealing with already-rate-converted values, premature wrapped
counters
shouldn't be an issue (?)
Cheers
-- Mark
|