in reply to Determining whether a value is zero.

The dualvar part was hard :)

Replies are listed 'Best First'.
Re^2: Determining whether a value is zero.
by Anonymous Monk on Mar 10, 2011 at 12:35 UTC
Re^2: Determining whether a value is zero.
by JavaFan (Canon) on Mar 10, 2011 at 13:05 UTC
    Close, but it reports dualvar (0, "0 ") not to be a zero.
      You only defined the expected values for
      Scalar::Util::dualvar 0, 1; Scalar::Util::dualvar 1, 0;
      So the effect you mentioned seems to be a specification-issue ;-)
      I give up. I cannot tell dualvar 0,"0 " from "0 ":
      use Devel::Peek; use Scalar::Util qw/dualvar/; my @x = ("0 ",dualvar(0,"0 ")); (10.2+$_).$_ for @x; Dump $x[0]; Dump $x[1];
      gives
      SV = PVNV(0x830ef78) at 0x8310564 REFCNT = 1 FLAGS = (IOK,NOK,POK,pIOK,pNOK,pPOK) IV = 0 NV = 0 PV = 0x835465c "0 "\0 CUR = 2 LEN = 4 SV = PVNV(0x830ef8c) at 0x8310584 REFCNT = 1 FLAGS = (IOK,NOK,POK,pIOK,pNOK,pPOK) IV = 0 NV = 0 PV = 0x833b77c "0 "\0 CUR = 2 LEN = 4

        Which I find to be good evidence that whatever is in JavaFan's mind to motivate this bizarre (even nonsensical or illogical) line he is trying to draw under the label of "is zero" is also not the most logical.

        His own impression that the declaring of "" and "0" as the only false strings being a highly arbitrary decision also hints that he has some seriously flawed mental model of how Perl works. A few Perl-like languages that I have worked with have decided that "0" should be true while 0 should be false and my experience is that such actually leads to some real gotchas.

        I think that declaring "0.0" and "00" as "not zero" are the silliest of his requirements (but he forgot "0e0").

        I think the closest I can come to whatever he might be thinking of and is trying to convey with the label and examples he gave is:

        if( SvIOK($x) ? 0 == $x : '0' eq $x )

        But I also think that Perl has a few bugs where it sets SvIOK when it should only be setting SvIOKp. Sorry, I don't recall the details at the moment. I did at least verify that Perl correctly sets only SvIOKp (not SvIOK) for $x= 'ten'; 0+$x;.

        I also noticed that Perl sets SvIOK (and SvIOKp, of course) for $x= '0 '; 0+$x; (note the trailing space), which I suspect JavaFan finds unfortunate.

        I thought there was some standard module that supports SvIOK() from Perl code (instead of from XS code) but it doesn't appear to be in the 'Internals' package on my version of Perl and I didn't try to come up with the search to find such a module.

        Update: I also suspect that whether or not SvIOK (not just SvIOKp) gets set might depend on the result of looks_like_a_number() (which is exported by a couple of different modules, at least one of which does so rather badly). So looks_like_a_number($x) && 0==$x might be one stab at "is zero" except that JavaFan threw in dual-valued scalars as examples, and bizarre dual-valued scalars at that. This could lead to the following test:

        if( do{ no warnings; 0==$x } && SvIOK($x) )

        (the order matters) which might be equivalent to

        if( ( SvIOK($x) || looks_like_a_number($x) ) && 0 == $x )

        But this, of course, considers "00", "0.0", and "0e0" as being zero (as it should) and even considers "0 " as being zero (which I also agree with but concede is not quite as clear of a slam-dunk decision).

        Update: Another similar, perhaps equivalent, test would be:

        if( do { my $w= 0; local($SIG{__WARN__})= sub { $w= 1 }; 0 == $x && ! $w } )

        - tye