nysus has asked for the wisdom of the Perl Monks concerning the following question:

Another day, another coding mystery to scratch my head over. I have this code:

sub exists { ## no critic my $self = shift; return 0 if !$self->path; print Dumper $self->path; print Dumper (-e $self->path); return -e $self->path ? 1 : 0; }

This dumps:

$VAR1 = '/Users/bigo/perl5/my_modules/t/Dir/tmp/'; $VAR1 = !!1;

Why is the -e returning !!1 and not just 1?

$PM = "Perl Monk's";
$MC = "Most Clueless Friar Abbot Bishop Pontiff Deacon Curate Priest Vicar Parson";
$nysus = $PM . ' ' . $MC;
Click here if you love Perl Monks

Replies are listed 'Best First'.
Re: Why is Dumper returning "!!1" for true file test?
by hv (Prior) on Jan 20, 2024 at 17:47 UTC

    I think it is mainly Data::Dumper being anal: Perl has a builtin constant called PL_Yes PL_sv_yes which is used internally for the boolean true value. The Dumper output is effectively saying that this isn't just any old constant 1, but the one and only PL_sv_yes. For a data structure with many copies I guess you'd get something of a memory saving compared to having many unique SVs.

    You can see the difference with Devel::Peek:

    perl -MDevel::Peek -wle 'Dump(1); Dump(!!1)' SV = IV(0x56346851ef48) at 0x56346851ef58 REFCNT = 1 FLAGS = (IOK,READONLY,PROTECT,pIOK) IV = 1 SV = PVNV(0x5634684f6050) at 0x5634684f43c8 REFCNT = 2147483644 FLAGS = (IOK,NOK,POK,READONLY,PROTECT,pIOK,pNOK,pPOK) IV = 1 NV = 1 PV = 0x563467d5e282 "1" CUR = 1 LEN = 0

    Builtins like this have an artificial refcount around 2^31 to indicate "should never be freed, not even accidentally".

    Perl v5.36 introduced an actual boolean type, but that doesn't make any noticeable difference to the value except that Devel::Peek now annotates the PV as "[BOOL PL_Yes]".

    Update: corrected the internal name of the SV; thanks @ikegami.

      &PL_sv_yes, to be precise. And &PL_sv_no is used for false. The third and final statically-allocated SV is &PL_sv_undef.

Re: Why is Dumper returning "!!1" for true file test?
by LanX (Saint) on Jan 20, 2024 at 17:51 UTC
    While 0 and 1 evaluate to false and true when tested, there is (was?) no real boolean type.

    And !!0 is a special dual var, which is "" in string, and 0 in numeric context

    Not having Booleans in Perl makes converting data from and to JSON problematic.

    I seem to remember that Booleans were introduced with one of the last Perl releases.

    So using !!0 and !!1 is both backwards and forward compatible.

    Think of them as replacements for the keywords true and false found in languages like JS

    Cheers Rolf
    (addicted to the Perl Programming Language :)
    see Wikisyntax for the Monastery

      I just started using the latest version of Perl from version 5.32. I hadn't heard about the new booleans. Hadn't heard about !!0 and !!1 either.

      These are definitely a weird beast. When I did print Dumper !!1 I expected it to print 1 but in fact it printed $VAR 1= !!1. This must be the dual var nature you refer to.

      Is there a basic tutorial on all this?

      $PM = "Perl Monk's";
      $MC = "Most Clueless Friar Abbot Bishop Pontiff Deacon Curate Priest Vicar Parson";
      $nysus = $PM . ' ' . $MC;
      Click here if you love Perl Monks

        > Hadn't heard about !!0 and !!1 either.

        I hope it's clear that ! is just the logical negation operator.

        Double negations are a very common idiom, you will find it in many languages, also in JS.

        !!$a is in the same idiomatic niche like 0+$a or "".$a of explicit casting to a certain type without altering the value. Just Boolean now instead of number or string.

        Cheers Rolf
        (addicted to the Perl Programming Language :)
        see Wikisyntax for the Monastery

        I hadn't heard about the new booleans.

        They're not new. They've existed for a very long time. At least since Perl 5.6 in 2000, but probably long before that. What was missing were functions whose sole purpose was to return them. That's what was recently introduced. And that's why we used !!0 and !!1 to produce them before that.

        I'm not aware of a single perldoc discussing all details, like it's done in MDN for JS.

        (Especially as it's mostly internal stuff which could change and the effects are supposed to be DWIM. Like I said most problems arise when converting to other languages, esp. JS)

        But you can gather them from various places like perlop or perlglossary .

        FWIW and I don't think !!1 used to be dualvar (see Scalar::Util ) prior to 5.36.

        Cheers Rolf
        (addicted to the Perl Programming Language :)
        see Wikisyntax for the Monastery

      The real question is why it returns "!!0" and "!!1" instead of "!1" and "!0". Saves a character and a runtime op...
        > Saves a character and a runtime op...

        And is confusing because you need to mentally negate it again, while !! is a common idiom.

        But the performance question occurred to me already I kind of expected constant folding to happen.

        update

        ha, indeed! :)

        DB<5> p B::Deparse->new()->coderef2text( sub{!!1} ) { use feature ... ; # shortened !0; } DB<6> p B::Deparse->new()->coderef2text( sub{!!0} ) { use feature ... ; # yadda !1; } DB<7> p $] 5.038002

        Cheers Rolf
        (addicted to the Perl Programming Language :)
        see Wikisyntax for the Monastery

Re: Why is Dumper returning "!!1" for true file test?
by nysus (Parson) on Jan 20, 2024 at 17:35 UTC

      And here is the actual change to the code: github repo

      $PM = "Perl Monk's";
      $MC = "Most Clueless Friar Abbot Bishop Pontiff Deacon Curate Priest Vicar Parson";
      $nysus = $PM . ' ' . $MC;
      Click here if you love Perl Monks