Beefy Boxes and Bandwidth Generously Provided by pair Networks
Clear questions and runnable code
get the best and fastest answer

Or Operator

by Anonymous Monk
on Jul 30, 2004 at 22:48 UTC ( #378825=perlquestion: print w/ replies, xml ) Need Help??
Anonymous Monk has asked for the wisdom of the Perl Monks concerning the following question:

In my script, I use:
my $page = $cgi->param("page") or "login";

But it always uses $cgi->param("page"), even if the return value is undef. I remember using this in another program and having it work . . . what am I doing differently? Isn't this supposed to work?


Comment on Or Operator
Re: Or Operator
by rjahrman (Scribe) on Jul 30, 2004 at 22:53 UTC
    (It's me again.)

    BTW, I got it to work with:
    $page = $cgi->param("page") or $page = "login";

    But this:
    my $page = $cgi->param("page") or $page = "login";
    Fails. Why? Is there something I can change to make it work?

      my $page = $cgi->param("page") or $page = "login";
      fails because that second $page is really the global variable; the scope where "$page" refers to the my variable only starts on the following statement. use strict would have alerted you to this (unless you have an outer $page, which is not a good idea for keeping your code maintainable.)
Re: Or Operator
by fruiture (Curate) on Jul 30, 2004 at 23:04 UTC

    The magic term is "operator precedence", it determines the order of execution or your atomic expressions.

    A = B or C; # as "=" has higher precedence than "or" it binds it's # arguments "tighter", so this is equivalent to (A = B) or C; # so your expression is a disjunction # which executes the left operand (A = B) # being an assignment, which returns B in the end # and if that's false, the disjunction (or) # returns C, which is irrelevant, because that's in void # context # but you want A = (B or C) # because that's an assignment, an assignment # evaluates the right operand first (B or C) # which itself is a disjunction again and works as described # above, returning B if true, otherwise C # and that is then assigned to A, which must be an lvalue # that means in Perl my $page = ( $cgi->param("page") or "login" ); # or by using the high-precedence-OR "||" my $page = $cgi->param("page") || "login"; # because "||" has higher precedence than "="

    see perlop

      I have another similar line:
      $ftp = Net::FTP->new("ftp.$dom", Debug => 0) or $loginerror = "Error message.";

      Should this work like I think it does?

        If you think it will set $ftp to the result of the new method call, and if that was false set $longin error, it will.
Re: Or Operator
by Avitar (Acolyte) on Jul 30, 2004 at 23:15 UTC
    my $page = $cgi->param("page") Or "login";

    should prob be rewritten as a conditional statement for clairy...

    my($page) = $cgi->param("page"); if($page eq ""){ $page = "login";}

    Try it with a lowercase 'or'; Remember if it is worth writing, it is worth writing clear... if possible even difficult code should be understandable by even the most unexperianced.
      I think this is the clearest and most concise way to express it: my $page = $cgi->param("page") || "login"; You might say that inexperienced people won't understand it, but once they see it a few hundred times (because this is a very common way of doing it), they'll probably get it.
        Then again, if there is a chance that $cgi->param("page") will be 0 - and you want to accept that, || will not work correctly. We'll get // (defined-or) in Perl 5.10, fortunately.

      Except that will give you warnings if the page parameter is actually non-existent.

      You want to test definedness as well as emptiness.

      my $page = $cgi->param( "page" ); unless( defined $page and $page ne "" ){ $page = "login"; }

      Of course that's pretty clusmy and contains lots of unnecessary punctuation. Let's use a statement modifier instead:

      my $page = $cgi->param("page"); $page = "login" unless defined $page and $page ne "";

      Makeshifts last the longest.

Re: Or Operator
by thor (Priest) on Jul 31, 2004 at 14:27 UTC
    As was stated above, you're having problems with operator precedence. Consider the following two one-liners:
    perl -le '$a = undef or 1; print $a' perl -le '$a = undef || 1; print $a'
    You may have to change the single-quotes to double-quotes to get the above examples to run from the command line, depending on what platform you're on

    As perlop tells us, 'or' has lower precedence than '=', while '||' has higher precedence than '='. So the first one-liner is equivalent to:

    perl -le '($a = undef) or "foo"; print $a'
    whereas the second one is equivalent to:
    perl -le '$a = (undef or "foo"); print $a'


    Feel the white light, the light within
    Be your own disciple, fan the sparks of will
    With all of us waiting, your kingdom will come

Re: Or Operator
by VSarkiss (Monsignor) on Jul 31, 2004 at 16:46 UTC

    The answers above address your question directly. If you ever need to figure this out on your own, the B::Deparse module, which comes standard with every Perl distribution, can be very helpful:

    $ perl -MO=Deparse -e 'my $foo = bar() or baz()' baz() unless my $foo = bar(); -e syntax OK $ perl -MO=Deparse -e 'my $foo = bar() || baz()' my $foo = bar() || baz(); -e syntax OK
    You can see how the two are interpreted very differently.

Log In?

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

How do I use this? | Other CB clients
Other Users?
Others imbibing at the Monastery: (4)
As of 2014-10-21 00:05 GMT
Find Nodes?
    Voting Booth?

    For retirement, I am banking on:

    Results (93 votes), past polls