User: Password:
|
|
Subscribe / Log in / New account

Affects Perl too

Affects Perl too

Posted Mar 14, 2014 17:37 UTC (Fri) by jtc (guest, #6246)
In reply to: Affects Perl too by bracher
Parent article: A false midnight

"perl -e 'use DateTime; my $d = DateTime->now(time_zone => "UTC")->set(hour => 0, minute => 0, second => 0); print $d ? "true" : "false","\n";'"

The object you're testing, $d, is a DateTime object, while in the given python example, the object is being tested is a time object, so your example is not equivalent. (You might think $d->time would produce a Time object and thus be equivalent, but it just produces a string that evaluates to true.) DateTime in perl does not (apparently) use or expose a Time object, so there perhaps is no equivalent comparison. (False dates - as opposed to times - are another issue - but we might have a hard time defining what is a 0 date.)

However, if you evaulate a zero hour, minute, or second in perl you do get false, as this example shows:

#!/bin/perl
use Modern::Perl;
use DateTime;
use Data::Dumper;
sub execute {
my ($o, $msg) = @_;
say "$msg: ", Dumper($o);
say 'o: ', ($o? 'true': 'false');
say '=' x 66;
}

my $d = DateTime->new(time_zone => 'UTC', year => 0, month => 1, day => 1,
hour => 0, minute => 0, second => 0);
execute($d, 'year 0 ...'); # true
execute($d->time, 'time 0 ...'); # true
execute($d->second, 'second 0 ...'); # false
execute($d->minute, 'minute 0 ...'); # false
execute($d->hour, 'hour 0 ...'); # false
execute($d->hour + $d->minute + $d->second, 'h+m+s 0 ...'); # false


(Log in to post comments)

Affects Perl too

Posted Mar 14, 2014 18:13 UTC (Fri) by mbunkus (subscriber, #87248) [Link]

Simply because the three getter methods return integers and not objects. Of course an integer of 0 is false in Boolean contexts in Perl. The whole point of the article is that certain objects evaluate to false in Python while "if obj: …" is a common way of checking whether or not obj currently holds an object instance.

Therefore your comparison is a bit besides the point.

Affects Perl too

Posted Mar 14, 2014 22:44 UTC (Fri) by jtc (guest, #6246) [Link]

"Therefore your comparison is a bit besides the point."

The point of my post was simply to point out that bracher's example compared a DateTime in perl with a Time in python - two different classes with different semantics - and thus not a valid comparison. I wasn't addressing the article - at least directly.

To make this point only my first sentence was needed ("The object you're testing ... not equivalent"). The rest was a - perhaps unnecessary - elaboration of the types involved with respect to DateTimes and Times in python vs perl (and yes, hour, minute, and second in perl evaluate to integers) and how, when it comes to Boolean evaluation, this leads to complexity and possible confusion. I'll grant that this is off-topic from the article.

On the other hand, I think it might be relevant (to the article) to point out that such complexity and confusion that result from regarding some instances of zero-ness as 'false' and other instances as 'not false' can cause problems that lead to defects and that it's wise not to use this idiom, at least for large projects. (Obviously, this puts me on the side of those arguing for midnight not evaluating to false in python, although I go even further to say "don't allow such an idiom in the code") The best way to avoid the idiom is to not allow it in the language (as is the case in statically-typed languages like Java [though not the case in C or C++]), but that's probably not practical for perl or python (or ruby, where 0 is true), since much existing code, obviously, uses these idioms. In that case all you can do, I suppose, is follow a coding standard that outlaws such comparisons (and perhaps use a lint-like tool to find violations).

(I elaborated on this point a bit more in another post:
http://lwn.net/Articles/590778/ )

Affects Perl too

Posted Mar 15, 2014 8:30 UTC (Sat) by mbunkus (subscriber, #87248) [Link]

Almost each and every language has its own rules which values it considers false in Boolean contexts. They're varied too much to approach remembering them with logic. You just have to learn them by heart.

C: the value 0; C++: 0 / nullptr (C++11 and newer) or depending on the class if operator bool is overloaded; Perl: undef / () / 0 / "0" (but not "0E0" or other strings which evaluate to 0 if taken in a numeric context) or depending on the class if bool conversion is overloaded; Lisp: depending on the Lisp dialect in question, somethings nil and the empty list (), sometimes only nil, sometimes nil and the Boolean type false as in Clojure); Ruby: nil and the Boolean false…

Therefore I consider saying anything along the lines of »0 is always/never supposed to be false« to be the wrong approach.

I fully agree that Boolean conversion for instances of a time-based classes (no matter if it's just the time component or a date as well or even both of them) is harmful. Remembering special rules like this leads to mistakes, it always does. There are useful cases for this kind of overloading, but they're rare: e.g. a TriBool class representing True/False/Unknown.

Affects Perl too

Posted Mar 15, 2014 10:35 UTC (Sat) by peter-b (subscriber, #66996) [Link]

I found myself thinking about this last night -- I quite like languages where there is one and only one "false" value. Like Scheme:

> Of all the standard Scheme values, only #f counts as false in conditional expressions. Except for #f, all standard Scheme values, including #t, pairs, the empty list, symbols, numbers, strings, vectors, and procedures, count as true.

The reason I like this is that it removes all uncertainty about what, exactly, a conditional expression is testing on.

Affects Perl too

Posted Mar 15, 2014 15:03 UTC (Sat) by khim (subscriber, #9252) [Link]

My position is different: I'm Ok with multiple “false” values in statically-typed languages (if any single type can have exactly one “false” value) but to me it looks like crazy thing to do with dynamically typed languages!

I mean: if I see something like if (i/*int*/) … or if (p/*pointer*/) … in C I know that there can be exactly one value which will be interepreted as false in this particular place. That is: language has many possible false values, but each particular point in a program can employ just one of them! I dislike tricks like std::ios::operator bool for that reason (yes, it's clever and sometimes it looks cool, but it erodes concept of “false” value).

But with dynamically typed languages this justification flies right out of the window: you can pass around “real” “false” everywhere, why would you need surrogate ones? They will just complicate everything for no good reason!

Perl, python, php - they all adopted C concept of “zero of any type is “false”” without thinking when they had no need for that kludge! This is a pity, really, but I'm afraid we are stuck with this decision: such change when applied to popular types will just break way too many programs.

Affects Perl too

Posted Mar 16, 2014 5:43 UTC (Sun) by jtc (guest, #6246) [Link]

"Therefore I consider saying anything along the lines of »0 is always/never supposed to be false« to be the wrong approach."

I agree.

"I fully agree that Boolean conversion for instances of a time-based classes ... is harmful. ..."

We appear to be in 100% agreement. :-)


Copyright © 2017, Eklektix, Inc.
Comments and public postings are copyrighted by their creators.
Linux is a registered trademark of Linus Torvalds