Hi guys.

In the php book I am currently reading, there is a snippet of code that doesn't make 100% sense to me:

<?php

if(!($handle = fopen("myfile.txt", "r"))) die("cannot open file");

?>

I understand what this code does and what it is for, but I don't understand why (in the book I am reading) it isn't typed up like this instead:

<?php

if(!$handle = fopen("myfile.txt", "r")) die("cannot open file");

?>

.... in other words, I don't get why (in the book I am reading) there needs to be extra parenthesis's:

if(!($handle = fopen("myfile.txt", "r")))

If I take them out and type it up like this:

if(!$handle = fopen("myfile.txt", "r"))

.... it appears to still work the same.

I don't understand why the extra parenthesis are even needed?

Paul.

    Refer to the PHP manual's table on operator precedence. You will see that the logical operator ! has a higher precedence than the assignment operator =

    Therefore, this:

    (!$handle = fopen("myfile.txt", "r"))

    is equivalent to:

    ((!$handle) = fopen("myfile.txt", "r"))

    Since "the value of an assignment expression is the value assigned", my guess is that the value of the above expression is thus equivalent to:

    (fopen("myfile.txt", "r"))

    which clearly is not equivalent in value to:

    (!($handle = fopen("myfile.txt", "r")))

    since the latter is equivalent in value to:

    (!fopen("myfile.txt", "r"))

      So you are saying that putting:

      $handle = fopen("myfile.txt", "r")

      .. inside parenthesis will make this particular snippet run first, before the not (!) operator is executed?

      Paul.

        laserlight wrote:

        You will see that the logical operator ! has a higher precedence than the assignment operator =

        Except see the note toward the bottom of that page (just above the user contributions). It's one of the things that deservedly contributes to PHP's reputation. So using the extra parentheses makes the code look less stupid.

          Paul help! wrote:

          .. inside parenthesis will make this particular snippet run first, before the not (!) operator is executed?

          Yes, or rather the grouping of subexpressions becomes clear such that this must be the resulting order of operations.

          Weedpacket wrote:

          Except see the note toward the bottom of that page (just above the user contributions). It's one of the things that deservedly contributes to PHP's reputation. So using the extra parentheses makes the code look less stupid.

          The note states what I have stated, so there is no "except", unless you are saying that the ! operator negates the value of the assignment expression rather than being superfluous in that context, in which case PHP would be inconsistent.

            No, the note says that

             (!$handle = fopen("myfile.txt", "r"))  

            is equivalent to

              (!($handle = fopen("myfile.txt", "r")))  

            and not equivalent to

             ((!$handle) = fopen("myfile.txt", "r"))  

            (which wouldn't make much sense anyway, since what would it mean to assign to a boolean value?)

            The negation operator does negate the value of the assignment expression; if the text appearing in the die() statement following is to be believed, the test overall is supposed to succeed if the fopen fails and the value of the assignment expression is false. So in

             (!$handle = fopen("myfile.txt", "r"))  

            the assignment is evaluated (and the resulting value assigned to [font=monospace]$handle[/font] as a side effect) before the negation, despite the latter having higher precedence.

            And yes, it does mean PHP is inconsistent.

              Weedpacket wrote:

              No, the note says that

              No, it doesn't. It says that such an expression is allowed, i.e., it is syntactically correct with some valid semantics, yet the semantics is not specified in the note, other than with respect to the value of the destination of the assignment.

              EDIT:
              That said, I suppose one can say that since the destination of the assignment is specified, it follows that the assignment subexpression really is grouped separate from the negation, but I'd say that this is not clear: my interpretation is that the destination of the assignment would be negated, but this is superfluous (at least in this case: perhaps with further chaining it wouldn't be superfluous) since the result of the entire expression would be the result of the assignment, following the precedence rules.

                I'd say:

                $handle = fopen('myfile.txt', 'r') or die('Could not open file');
                

                😉

                  Not applicable if one wants to convert to graceful error handling later though :p

                    laserlight;11057531 wrote:

                    Not applicable if one wants to convert to graceful error handling later though :p

                    $handle = fopen('myfile.txt', 'r') or my_graceful_error_handler("could not open file");
                    

                    😉

                    PS:

                    function my_graceful_error_handler($msg)
                    {
                        die($msg);
                    }
                    

                    :p

                      my interpretation is that the destination of the assignment would be negated

                      No, the note says "the return value of foo() is put into $a". Not the negation of the value - and not the negation of the destination either (whatever that would mean).

                      since the result of the entire expression would be the result of the assignment, following the precedence rules.

                      Which aren't being followed here: in spite of the fact that [font=monospace]=[/font] has lower precedence than [font=monospace]![/font], in this expression the [font=monospace]$handle[/font] between them is - to use the terminology of the documentation - more "tightly" bound to the assignment. This is why the note was added (specifically, in response to https://bugs.php.net/bug.php?id=17180).

                      The overriding of precedence that happens here is an artefact of how the parser was written in some really old version of PHP and has been deliberately reimplemented since for the sake of backward-compatibility. I'm not about to embark on a suck-it-and-see survey of languages with similar syntax, but I suspect that the majority of them would whine about an "invalid assignment" or some such if the "extra" parentheses aren't there.

                      You've been working in Python too long - you're starting to think every language makes as much sense. 🙂

                        Write a Reply...