Live data from Hacker News

Please reconsider the Boolean evaluation of midnight

mail.python.org

201–210 of 218 posts

Re: Please reconsider the Boolean evaluation of midnight

#201
post #182
post #176

Earlier quoted context omitted.

What do those code samples have anything to do with abelian groups? Abelian groups are those whose group operator is commutative, i.e. a + b = b + a for all a and b. The code examples seem to be referring to the existence of an identity element, which is necessary for all groups.

I think what he was saying was: * You should use + only for operations that form an abelian group across the domain * In those cases, it makes sense for the identity to be false. The truth is, time doesn't have a sensible addition/combination operator, never mind an identity and inverse, so it isn't even a group.

Okay, I definitely buy that. It makes sense to add a duration (timedelta in Python) to a time, but not to add times to one another.

This is venturing off topic, but if you really wanted to, you could define addition for times in terms of timedeltas. It makes sense to subtract times and get a timedelta, so you could define addition as the subtraction with signed times and signed timedeltas. So, since `time(today) - time(yesterday) = timedelta(1 day)`, we could say that `time(today) + time(yesterday) = -timedelta(1 day)` and `time(today) - -time(yesterday) = timedelta(1 day)`. It's a bit strange to define the notion of a signed time object, but it could work.

Re: Please reconsider the Boolean evaluation of midnight

#202

If I understand the argument there correctly, the responder is saying: Nobody should ever use this functionality, instead they should always check that the date is not None. So, we should leave this broken, because we don't want to break backwards-compatibility with that class of applications that nobody should ever write. That philosophy, taken to its logical conclusion, results in everything being broken forever.

Yes. This is where Linus would step in and say "SHUT THE FUCK UP! We don't break user space, EVER!" Developers who enter into the mindset that the users of their code are using it "wrong" are a blight and will always be a blight. Too bad Python has a BDFL and not a Raging DFL.

Given approximately zero people using this datetime behaviour correctly, maybe one or two who tried to use it correctly and failed, and thousands of people who have bugs because they didn't expect it, I'm not sure changing it to be sensible counts as breaking user space in any practical sense...

Re: Please reconsider the Boolean evaluation of midnight

#203
post #150

INADA Naoki's argument [1] is succinct and insightful. I feel zero value of non abelian group should not mean False in bool context. () + () == () "" + "" == "" 0 + 0 == 0 timedelta() + timedelta() == timedelta() time() + time() => TypeError [1] https://mail.python.org/pipermail/python-ideas/2014-March/02...

If that were true, it would mean that dict should not support bool: >>> {} + {} Traceback (most recent call last): File " ", line 1, in TypeError: unsupported operand type(s) for +: 'dict' and 'dict' >>> bool({}) False Since I find bool(a_dict) to be very useful, and the lack of a_dict+b_dict to be reasonable (precisely because it's non-abelian!), I conclude that logic is cute, but not that relevant. Those who think…

Honestly, I would be fine with nothing supporting bool, and requiring `if` conditions to be bools. Arrays and dictionaries could have methods like `.empty?` that return a bool. Strings could have `.blank?`. Obviously, I'm stealing the methods from Ruby, although Ruby also has its own notions of truthiness of non-booleans.

Re: Please reconsider the Boolean evaluation of midnight

#204
post #203
post #150

Earlier quoted context omitted.

If that were true, it would mean that dict should not support bool: >>> {} + {} Traceback (most recent call last): File " ", line 1, in TypeError: unsupported operand type(s) for +: 'dict' and 'dict' >>> bool({}) False Since I find bool(a_dict) to be very useful, and the lack of a_dict+b_dict to be reasonable (precisely because it's non-abelian!), I conclude that logic is cute, but not that relevant. Those who think…

Honestly, I would be fine with nothing supporting bool, and requiring `if` conditions to be bools. Arrays and dictionaries could have methods like `.empty?` that return a bool. Strings could have `.blank?`. Obviously, I'm stealing the methods from Ruby, although Ruby also has its own notions of truthiness of non-booleans.

There are many languages which do something like that. Python is not one of them. Personally, I find it useful to write things like "if x:" and not worry about if x is None or x is s list of characters or x is a string of characters.

Re: Please reconsider the Boolean evaluation of midnight

#205
post #204
post #203

Earlier quoted context omitted.

Honestly, I would be fine with nothing supporting bool, and requiring `if` conditions to be bools. Arrays and dictionaries could have methods like `.empty?` that return a bool. Strings could have `.blank?`. Obviously, I'm stealing the methods from Ruby, although Ruby also has its own notions of truthiness of non-booleans.

There are many languages which do something like that. Python is not one of them. Personally, I find it useful to write things like "if x:" and not worry about if x is None or x is s list of characters or x is a string of characters.

I guess it comes down to the much more fundamental dichotomy between dynamic and static typing. I think most programmers would agree that having a function that accepts strings, lists, and dicts into the same argument (and thus sends them all through the exact same code path) is usually a bad idea. In Rails, I often find myself calling `to_i` or `to_s` just so that I can safely reason about that variable in the subsequent code.

Re: Please reconsider the Boolean evaluation of midnight

#206
post #205
post #204

Earlier quoted context omitted.

There are many languages which do something like that. Python is not one of them. Personally, I find it useful to write things like "if x:" and not worry about if x is None or x is s list of characters or x is a string of characters.

I guess it comes down to the much more fundamental dichotomy between dynamic and static typing. I think most programmers would agree that having a function that accepts strings, lists, and dicts into the same argument (and thus sends them all through the exact same code path) is usually a bad idea. In Rails, I often find myself calling `to_i` or `to_s` just so that I can safely reason about that variable in the subse…

Which means you don't like generic programming or templates. That in turn tells me something about the types of programmers you know. For example, neither you nor they likely use the Boost libraries.

In any case, it's a bit of a distraction. "Most programmers" aren't all that good at programming, or judging what makes a good language. How important then is it that I weigh your projection of their ideas of right or wrong?

In Python it absolutely, positively, without a doubt is not a bad thing to have a function which accepts multiple data types. Some trivial examples are len() and iter(). Since you don't like the core language design in Python, I think it's safe to argue that your sensibilities are going to have many objections to any other part of the language.

Re: Please reconsider the Boolean evaluation of midnight

#207

Earlier quoted context omitted.

Indeed, the first thing that came into my mind when reading this was "You wouldn't have this problem if the only valid type in a conditional was boolean."

It's against the grain to think this way in dynamic languages because variables don't have types, only individual values do. Ill-thought truthiness rules are the real problem. IMO every value except boolean false (and, if you insist, nil/null) should be truthy in a dynamic language.

> It's against the grain to think this way in dynamic languages because variables don't have types, only individual values do.

So? "The only valid type for a conditional is boolean" still works if types only apply to values. Under that principle, anything but True or False value encountered in evaluating the condition of an if statement ought to throw a TypeError, not be evaluated for truthiness. If you are expecting something else, call an explicit, use-case-appropriate function to get the right in-context truth value.

(Note, I'm not saying Python should do this, I'm explaining how the logic applies to Python without any contradiction to the "variables don't have types, values do" principle.)

> IMO every value except boolean false (and, if you insist, nil/null) should be truthy in a dynamic language.

I think that's better than what Python does (Ruby does that by default, with nil included as false, though it is IIRC possible-but-extremely-strongly-discouraged to override the default truthiness of objects so you could have classes with falsey values), and I lean toward preferring that approach, but the idea that a dynamic language would do well to just allow True and False as the only valid (non-error-producing) values for an "if" statement is not, IMO, without some merit.

Re: Please reconsider the Boolean evaluation of midnight

#208
post #200
post #150

Earlier quoted context omitted.

If that were true, it would mean that dict should not support bool: >>> {} + {} Traceback (most recent call last): File " ", line 1, in TypeError: unsupported operand type(s) for +: 'dict' and 'dict' >>> bool({}) False Since I find bool(a_dict) to be very useful, and the lack of a_dict+b_dict to be reasonable (precisely because it's non-abelian!), I conclude that logic is cute, but not that relevant. Those who think…

bool({}) should raise an exception, if we're being strict. You could try to define the addition of keys like you suggest, but you need to force a value type which defines a + operation into the same type. Which is what Counter() does, below (appending strings). Python is dynamically typed, so you can't maintain these expectations. Therefore, summation and bool({}) should be an error, or merely "true" (ie, yes, it exi…

Good thing Python isn't a strict language then. That would be Scheme. ;)

Re: Please reconsider the Boolean evaluation of midnight

#209
post #206
post #205

Earlier quoted context omitted.

I guess it comes down to the much more fundamental dichotomy between dynamic and static typing. I think most programmers would agree that having a function that accepts strings, lists, and dicts into the same argument (and thus sends them all through the exact same code path) is usually a bad idea. In Rails, I often find myself calling `to_i` or `to_s` just so that I can safely reason about that variable in the subse…

Which means you don't like generic programming or templates. That in turn tells me something about the types of programmers you know. For example, neither you nor they likely use the Boost libraries. In any case, it's a bit of a distraction. "Most programmers" aren't all that good at programming, or judging what makes a good language. How important then is it that I weigh your projection of their ideas of right or wr…

Do any of your examples (generic programming, templates, Boost libraries) actually utilize the concept of testing the truthiness of an object of unknown type? I think your criticism is invalid. I like generic programming in Java, though I admittedly have not used templates or Boost libraries for anything substantial.

> In Python it absolutely, positively, without a doubt is not a bad thing to have a function which accepts multiple data types. Some trivial examples are len() and iter().

I'm not arguing that this shouldn't be the case. My argument is specifically about bool(). If len() or iter() worked as strangely with basic data types as bool(), then I would probably extend my argument to cover them as well. For any data type I'm aware of that works with len() or iter(), the logic of what is returned is pretty clear and obvious, but that's not the case (in my opinion) with bool(). If len(-5) returned 5 (i.e. absolute value or "length from zero") then I would argue that it's a bad idea.

Re: Please reconsider the Boolean evaluation of midnight

#210

Earlier quoted context omitted.

Indeed, the first thing that came into my mind when reading this was "You wouldn't have this problem if the only valid type in a conditional was boolean."

It's against the grain to think this way in dynamic languages because variables don't have types, only individual values do. Ill-thought truthiness rules are the real problem. IMO every value except boolean false (and, if you insist, nil/null) should be truthy in a dynamic language.

> variables don't have types, only individual values do.

It really depends on what language you're using. This is more or less true in Python, Ruby, and Javascript. In Lisp generic methods you can specify the type for the input variables and be guaranteed that if you are inside the method the parameters are of that specific type. For optimization reasons you can also declare to the compiler that variables are a specific type. This is really important when doing numeric computations in a tight loop. I've had 50% - 80% performance improvement by declaring types (amounting to hours of run time). I think Groovy and Clojure also allow this but I don't know much about those two.

There's also the maintenance issue though. After a few years of maintaining a fairly large Lisp project I've become pretty convinced that the only way to stay sane, at least for me, is to treat it as a statically typed language. I have asserts and check-type macros all over the place. If variables may have multiple types they can be checked against '(or type1 type2) but things do become more complicated then.

Post reply on HN