in reply to Determining whether a value is zero.

use B qw( svref_2object SVf_IOK SVf_NOK SVf_POK ); sub is_zero { my $sv = svref_2object(my $ref = \$_[0]); my $flags = $sv->FLAGS; return $sv->IVX == 0 if $flags & SVf_IOK; return $sv->NVX == 0 if $flags & SVf_NOK; return $sv->PV eq "0" if $flags & SVf_POK; return 0; }

Replies are listed 'Best First'.
Re^2: Determining whether a value is zero.
by JavaFan (Canon) on Mar 11, 2011 at 10:59 UTC
    Give that man a cigar (or another vice to his liking). Not only did ikegami understood and solved the challenge, he didn't feel the need to argue the rules weren't to his liking.

    If there's a way to do it without having to break encapsulation of value and peek at their internal flags, I don't know such a way - but I'd love to hear about it.

      If there's a way to do it without having to break encapsulation of value and peek at their internal flags, I don't know such a way - but I'd love to hear about it.

      Tried and failed. Need to find something that can distinguish between absent IV and NV and zero IV or NV. This boils down to finding something that

      • favours IV and NV over PV, and
      • doesn't silently numify the PV if it looks_like_number.

      Lots of operations match the first requirement (arithmetic and bitwise ops) but I can't think of anything that matches both.

      To be fair, I would have mentioned something about the rules not being practical if it hadn't already been said. In case you were actually planning on using this and didn't realize the consequences.
      isn't dualvar's made by peeking at the internals ? I think it's unfair to try to detect something without the same techniques used to create that something, but hey it's your challenge.

      On a unrelated note, is dualvar(undef,"string") zero ?
        isn't dualvar's made by peeking at the internals ?
        Eventually, everything Perl is done by doing something with the internals. However, all dualvar exposes is that values can have both a numeric and a string value. One could change large parts of the internals without having to change the interface of dualvar. However, the solution presented queries internal bits of the SV structure.
        is dualvar(undef,"string") zero ?
        Yes. There's no way to store "undef" in the IV slot of an SV. AFAIK, the undef has been (auto)cast to 0 before the SV will be created.
Re^2: Determining whether a value is zero.
by choroba (Cardinal) on Mar 11, 2011 at 08:02 UTC
    It works only if I do not touch (i.e. expose it to various contexts) the variable before running the test:
    for my $x (0, "0", 0.0, dualvar(0,1), dualvar(0,"0 "), '----------------', 1, "foo", "00", "0 ", undef, "", dualvar(1,0), "0.0", ) { print "$x before: ",is_zero($x),"\n"; my $y = ($x+1.1).$x; print "$x after: ",is_zero($x),"\n"; }

      It works as per the OP's spec. Don't blame me for his spec being awful!

      For strings,

      0+$x; #Upd: Or 1.1 or whatever

      is effectively

      $x = dualvar(0+$x, $x) if looks_like_number($x);

      The OP was clear that dualvar(0, $anything) should be considered zero.

        dualvar 0,"0 " is considered zero after the assignment to $y in my code. That is against the specification I fear...
        UPDATE: corrected.
      It works only if I do not touch (i.e. expose it to various contexts) the variable before running the test:
      Well, yes. That's because looking at variables in Perl can actually modify them.
Re^2: Determining whether a value is zero.
by ikegami (Patriarch) on Mar 11, 2011 at 18:32 UTC

    Some notes:

    It could be considered to break the pure Perl rule. B is written in XS. But hey, so are operators and both come with Perl.

    It doesn't call get magic or handle overloading.