Beefy Boxes and Bandwidth Generously Provided by pair Networks
Problems? Is your data what you think it is?
 
PerlMonks  

Variable assignment after logical OR

by rq-2102 (Acolyte)
on Oct 02, 2007 at 18:40 UTC ( #642199=perlquestion: print w/replies, xml ) Need Help??

rq-2102 has asked for the wisdom of the Perl Monks concerning the following question:

Hi Monks,

I've been having a bit of trouble with getting perl to act reliably following a logical OR statement in code. I want to perform multiple operations in case of a failure when opening a file for write, and so my choices would seem to be to call a subroutine or to set a flag indicating a failure. For example:

 open FILE, ">test.txt" || $failed_flag = 1;

The above example will not compile, I've also tried with using a &subroutine instead of a direct assignment with no luck. It compiles, but the subroutine seems to never actually run...
---------
Brian

Replies are listed 'Best First'.
Re: Variable assignment after logical OR
by FunkyMonk (Chancellor) on Oct 02, 2007 at 18:58 UTC
    It's all to do with the order in which operators get evaluated (precedance). In your open statement, || is evaluated before the comma, so your statement is parsed as open FILE, (">test.txt" || $failed_flag = 1); giving the syntax error.

    Perl has some super-low precedance operators (and, or and not). and and or can be used as statement modifiers. So, you can write:

    open FILE, ">test.txt" or $failed_flag = 1;

    Or, if you add parentheses to your original statement, you can write:

    open( FILE, ">test.txt" ) || $failed_flag = 1;

    That said, if you're using a modern perl, you are better off using the three-argument open and a lexical filehandle:

    open my $FILE, ">", "test.txt" or $failed_flag = 1;

    See here to read more about precedance

    update: missed a quote. Thanks toolic. not can't be used as a modifier.

      In your open statement, || is evaluated before the comma, so your statement is parsed as open FILE, (">test.txt" || $failed_flag = 1); giving the syntax error.

      Actually the  || operator also has higher precedence than the  = operator so it is parsed as open FILE, (">test.txt" || $failed_flag) = 1; which is why you get the error  Can't modify constant item in scalar assignment

        You're absolutely right of course and I should have noticed that. Thanks for pointing it out.

Re: Variable assignment after logical OR
by ikegami (Pope) on Oct 02, 2007 at 19:03 UTC

    You have a precedence problem.

    General rule:
    Use or to join statments together (where you'd otherwise use an if).
    Use || when you'll use the result of the operation (i.e. in an assignment, to pass to a function, etc).

    Omitting parens from function calls has a few pitfalls, including this one. You might be better off using them.

Re: Variable assignment after logical OR
by snopal (Pilgrim) on Oct 02, 2007 at 18:43 UTC

    Try this:

    open FILE, ">test.txt" or $failed_flag = 1;
Re: Variable assignment after logical OR
by johngg (Canon) on Oct 02, 2007 at 19:08 UTC
    snopal has pointed you towards using or instead of || because the former is a lower-precedence equivalent of the latter. Another way to solve your problem would be to use parentheses with your open so the || doesn't bind the file name and the flag together.

    open(FILE, ">test.txt") || $failed_flag = 1;

    It is often recommended these days to use the three-argument form of open with lexical filehandles, like this.

    open my $testFH, '>', 'test.txt' or $failed_flag = 1;

    Cheers,

    JohnGG

    Update: I really must learn to type faster :(

      Thanks all for the help and advice! For now I've switched from "||" to "or" but I'll definitely try to make a habit of using the new open statement as well, in this case it's not an option but it's good to know.
      --------- brian
        Why is it not an option?
Re: Variable assignment after logical OR
by Eimi Metamorphoumai (Deacon) on Oct 03, 2007 at 19:07 UTC
    Others have told you what's wrong with your code, but I'd like to mention that there are other options besides a flag value and a subroutine. In particular, I would suggest something like
    unless(open FILE, ">test.txt"){ #error handling code goes here }
A reply falls below the community's threshold of quality. You may see it by logging in.

Log In?
Username:
Password:

What's my password?
Create A New User
Node Status?
node history
Node Type: perlquestion [id://642199]
Approved by Sidhekin
help
Chatterbox?
and the web crawler heard nothing...

How do I use this? | Other CB clients
Other Users?
Others chilling in the Monastery: (3)
As of 2020-12-05 22:16 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?
    How often do you use taint mode?





    Results (65 votes). Check out past polls.

    Notices?