|
|

# A false midnight

## A false midnight

Posted Mar 14, 2014 21:24 UTC (Fri) by jtc (guest, #6246)
In reply to: A false midnight by fandingo
Parent article: A false midnight

Actually, I agree with your main point and wasn't meaning to argue against it. I didn't make it clear I was only disagreeing with the side issue that the start of something should evaluate to false. (And it was clear to me you weren't stating this proposition was your view.)

As far as your main point, I think your example/argument of dates never evaluating to false while times sometimes do is valid. On the other hand, someone might argue that something that can have a 0 value (such as a time) should be false when it's 0. But a date cannot really have a 0 value (since, as you implied, there is no 0th day of year 0 [disregarding whether there can actually be a year 0] and no 0th month - so you can never have a date [year/month/day] that evaluates to 0) and thus it's appropriate for a date to never evaluate to false. (This is not my argument, but one I think some people would make.)

To address that last argument, let me bring in the Baby object from my earlier post. You might have Baby == 0 (AKA baby.age == 0) and you might think of that as false. But why? What does false mean? It exists [otherwise it would be null/void and not evaluate to anything :-)] - doesn't existence imply truth?

I suppose I'm actually generalizing the argument - partly because some people will object to your argument for the reason I gave. I suggest that for a system that will be around for years and will be modified and extended, Boolean checks should be explicit (i.e., there should be no auto-conversion of a type into Boolean) - Instead of if (not currenttime), the code should read, for example: if (currenttime.is_midnight). IMO, this is clearer and much less error-prone. It's less likely that someone changing the code will make a mistake because the intent of the if ... clause wasn't clear to him. (I suppose you could say this is a long-winded way of saying what someone else suggested earlier: Make the code readable.)

I think part of the problem is the dual nature of languages such as perl and python (and, to some extent, ruby) - One purpose of these languages is to allow writing informal scripts (usually short and quick) that take care of an immediate need. The other is to develop applications, many of which will be quite large and will be around for a long time, and will be used by many people. For the first purpose it perhaps makes sense to allow, e.g., 0 => false; but for major projects I think it might not be a good idea.

A false midnight

Posted Mar 15, 2014 0:22 UTC (Sat) by fandingo (subscriber, #67019) [Link]

I pretty much entirely agree with you, so don't take these comments as a vigorous rebuttal.

> But a date cannot really have a 0 value (since, as you implied, there is no 0th day of year 0 [disregarding whether there can actually be a year 0] and no 0th month - so you can never have a date [year/month/day] that evaluates to 0) and thus it's appropriate for a date to never evaluate to false. (This is not my argument, but one I think some people would make.)

datetime.MINYEAR could be defined as 0, and I'm actually a little surprised that it is 1 because that seems incredibly arbitrary. As for having zero months and days, it's about about how you represent it. Months kind of naturally map this way if you have a list that represents the month names because 0-indexed makes that easier. Anyways, whether a month is zero-indexed or a time is tracked in a 12-hour AM/PM representation doesn't matter. That's the internal state of the object, which shouldn't leak out to users, but it does in the form of __bool__ for datetime.time.

> To address that last argument, let me bring in the Baby object from my earlier post. You might have Baby == 0 (AKA baby.age == 0) and you might think of that as false. But why?

It's obvious that some people (like Tim Peters) think this sort of behavior makes sense, but I would never write a class that did something like that. As you say, it's horribly unintuitive. If I read the line

if not my_baby:

there is a 0% that I would ever think that my_baby would be anything other than True or None (well, False if used as a sentinel but never due to __bool__). (And, I know that many people get upset of not using the pedantic "if my_baby is not None," but there's no reason for that if the object has no business being falsey.)

> It exists [otherwise it would be null/void and not evaluate to anything :-)] - doesn't existence imply truth?

I don't agree with this line of reasoning, which you go onto explain in more detail. The problem is that you're basically defining falsey behavior as NameError. That's actually an interesting thought where the sentinel None could be eliminated and a wider use of NameError used, but it would require substantial changes to Python and the development process. (You'd have to stop functions from implicitly returning None, get people to use exception handling far more, and so on.)

> Instead of if (not currenttime), the code should read, for example: if (currenttime.is_midnight). IMO, this is clearer and much less error-prone. It's less likely that someone changing the code will make a mistake because the intent of the if ... clause wasn't clear to him. (I suppose you could say this is a long-winded way of saying what someone else suggested earlier: Make the code readable.)

I take it a step further and believe that stdlib classes have no business implementing this sort of specialized behavior.

if currenttime == datetime.time(0, 0, 0):

That seems like unambiguously the correct answer. There are no surprises for the author or any subsequent readers.

> For the [informal script] purpose it perhaps makes sense to allow, e.g., 0 => false; but for major projects I think it might not be a good idea.

Yet, aren't the informal script writers the *least* likely to know about this behavior and also have the least tested code that is more likely to fall victim to unintentionally falsey behavior? Nick Coghlan said it best in the original article:

>> [...]having a caveat in your documentation isn't going to help, because people aren't even going to think to ask the question.

A false midnight

Posted Mar 20, 2014 15:54 UTC (Thu) by Wol (guest, #4433) [Link]

MINYEAR could be 0? Why?

Although the Western calendar has positive and negative years, AD and BC, it's interesting that it doesn't have a year 0. Although when you look at the history this is no surprise. The current numbering system from the (assumed) date of Jesus' birth was implemented at a time when there was no concept of 0.

Actually, this would be a perfect rational for why year 0 should be false :-)

There is no symbol in Roman Numerals for 0, and iirc, it was introduced to Western mathematicians round about 1000AD, some 600 years after the calendar was implemented.

Cheers,
Wol