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

Hi, Monks...

I'm unable to get a clear understanding of how the Boolean operators work in the following script:

#!/usr/bin/perl $pgm1 = "ls -l ."; $pgm2 = "ls -l /tmp/bogus/directory"; system ($pgm1) || print "program 1 succeeded\n"; system ($pgm2) && print "program 2 failed\n";

By my impaired thinking, I thought system ($pgm1) would deliver true and print "program 1 succeeded\n" would, in turn, not be carried out following the || (or) operator.

Please tell me where my thinking is wrong?

Thanks!

Replies are listed 'Best First'.
Re: Boolean (was Boolian) operators defy my understanding...
by philcrow (Priest) on Jun 20, 2007 at 14:38 UTC
    system is odd. It returns the exit status. By tradition, status zero means success (which happens to be false), while failures are reported by a number that you can look up to see what went wrong (these are non-zero and therefore true).

    Sometimes it helps to name the return value:

    my $failure = system...; if ( $failure ) { ... }

    Phil

    The Gantry Web Framework Book is now available.
      This now seems to be making sense to me, so please correct me if I'm wrong:

      A successful system call yields the bash exit code of "0", and the Perl interpretation of this "0" (as being a failure), permits execution of the "other" component of the || comparison operator.

      On the other hand, an unsuccessful system call produces an exit code other than "0", and is erroneously interpreted by Perl as "true". This accounts for Perl's action of allowing an unsuccessful system call to stand in as true for the first component of the "&&" operator.

      Please excuse me if this comes across as a lame discussion, but this issue has been difficult for me to understand.

      Thanks!

        Yes, you've got it. That's why I said system is odd. Most Perl functions return something that works in a boolean test (open ... or die), but not system. It uses the Unix shell behavior (all shells do this not just bash). So you have to reverse the sense of the test at very least. Really, you should know what the failure codes are and handle them as cases, as shown in another response.

        Phil

        The Gantry Web Framework Book is now available.
Re: Boolean (was Boolian) operators defy my understanding...
by ikegami (Patriarch) on Jun 20, 2007 at 14:40 UTC

    system doesn't return true/false. Please refer to the documentation. For example, if the command was launched successfully and the exit code of the child process is 0, system returns 0.

    my $rv = system(...); if ($rv == -1) { die("Unable to launch child: $!\n"); } if ($rv & 127) { die(sprintf("Error executing child: Child died with signal %d, %s c +oredump\n", ($rv & 127), ($rv & 128) ? 'with' : 'without', )); } if ($rv >> 8) { die(sprintf("Error executing child: Child exited with value %d\n", ($rv >> 8) )); } print("Child ran successfully\n");
      ikegami...

      I appreciate your comments and example code.

      I also have also found similar code (http://perldoc.perl.org/functions/system.html):

      You can check all the failure possibilities by inspecting $? like this:

      if ($? == -1) { print "failed to execute: $!\n"; } elsif ($? & 127) { printf "child died with signal %d, %s coredump\n", ($? & 127), ($? & 128) ? 'with' : 'without'; } else { printf "child exited with value %d\n", $? >> 8; }

      I'm curious as to what determines the use of 127 and 128 in this script, and what is meant by "$? >> 8"?

      Thanks!

        I'm curious as to what determines the use of 127 and 128 in this script

        The format of system's return value.

        system returns either -1, or a (at least) 32-bit value composed of three fields.

        bit F E D C B A 9 8 7 6 5 4 3 2 1 0 +---------------+-+-------------+ |xxxxxxxxxxxxxxx|c|sssssssssssss| +---------------+-+-------------+
        • s: Signal that caused the child to exit or 0 if the child existed normally.
        • c: A core dump was produced if 1.
        • x: Child's exit code (if s is zero).

        what is meant by "$? >> 8"?

        Perl operators are documented in perlop.

Re: Boolean (was Boolian) operators defy my understanding...
by grep (Monsignor) on Jun 20, 2007 at 14:39 UTC
    It's not a problem with the boolean operators - you didn't read about system

    Simply put, system returns 0 upon success, this is standard behavior for unix.

    For a more in-depth explanation read the docs for system

    grep
    1)Gain XP 2)??? 3)Profit

Re: Boolean (was Boolian) operators defy my understanding...
by Zaxo (Archbishop) on Jun 20, 2007 at 14:40 UTC

    I think your problem is with system, not the logical operators. Contrary to the rest of perl, system follows the os shell convention of returning false on success. That is confusing until you get used to it.

    The true value of a system call failure contains the exit status, which is the reason for the inverted logic. Success needs less bandwidth ;-)

    After Compline,
    Zaxo

Re: Boolean (was Boolian) operators defy my understanding...
by FunkyMonk (Bishop) on Jun 20, 2007 at 16:32 UTC
    Nobody seems to have replied with what I thought was a common idiom for system calls:

    system( "ls -l" ) == 0 or die;