Beefy Boxes and Bandwidth Generously Provided by pair Networks
Perl: the Markov chain saw
 
PerlMonks  

What is the difference between |= and ||=?

by Anonymous Monk
on Apr 07, 2009 at 13:22 UTC ( #756016=perlquestion: print w/ replies, xml ) Need Help??
Anonymous Monk has asked for the wisdom of the Perl Monks concerning the following question:

Hi,

What is the difference between |= and ||=?

my $var |= 1; my $var2 ||= 1;

In the example above, both $var and $var are set to the value 1. So what is difference between the two operators?

Many thanks in anticipation.

Comment on What is the difference between |= and ||=?
Download Code
Re: What is the difference between |= and ||=?
by Anonymous Monk on Apr 07, 2009 at 13:26 UTC
    perlop explains that || is "logical or" while | is "Bitwise Or"
Re: What is the difference between |= and ||=?
by jettero (Monsignor) on Apr 07, 2009 at 13:26 UTC
    One is bitwise and one is logical. See perlop for further details.

    -Paul

Re: What is the difference between |= and ||=?
by JavaFan (Canon) on Apr 07, 2009 at 13:33 UTC
    my $var3 += 1; my $var4 .= 1;
    Now $var3 and $var4 are all set to the value 1 as well.
Re: What is the difference between |= and ||=?
by gwadej (Chaplain) on Apr 07, 2009 at 13:35 UTC

    The fact that |= is a bitwise or and ||= is a logical or has a few consequences not shown in your code above. For example,

    $var = 2; $var ||= 1; # $var now has the value 2. $var |= 1; # $var now has the value 3.

    One non-obvious effect that is worth mentioning is shortcut behavior. The right hand side of ||= is not evaluated if the left hand side is true. But, both sides of |= are always evaluated.

    Update: Corrected term bitwise

    G. Wade
Re: What is the difference between |= and ||=?
by lostjimmy (Chaplain) on Apr 07, 2009 at 13:51 UTC
Re: What is the difference between |= and ||=?
by ikegami (Pope) on Apr 07, 2009 at 14:19 UTC

    The following sets the var to 1 too, and it even looks similar, so it must be the same operator as the other two, right?

    my $var3 = 1;

    Why does that bizarre logic keep surfacing? Operators are documented in perlop.

    In fact, you should be using my $var = 1; in this case. I'm surprised no one has mentioned that it makes no sense for my $var to be the LHS of |= or ||=.

    my $var |= 1; my $var2 ||= 1;
    means
    my $var; $var = $var | 1; ^^^^ Known to be undef since it was just created. my $var2; $var2 = $var2 || 1; ^^^^^ Known to be undef since it was just created.

      It's much clearer now, thanks :)

      I get warnings with hash references and I've used code such as to get around the problem:

      $some_href->{id} ||= 0;

      Is that a good style? If not, what are the alternatives?

        Assuming the empty string isn't a valid id, that will convert undef to zero.

        Whether it makes sense or not can only be derived from context, but it seems to me that you might be silencing the symptom, not fixing the problem. Why is id undef in the first place? Why would it makes sense to set it to zero when it is?

        $some_href->{id} ||= 0;
        Is that a good style?
        Whether or not it's good style depends on what you intend to do.

        The statement  $some_href->{id} ||= 0; will assign 0 to the hash element if the hash element is anything that Perl evaluates as false, e.g., undef, 0, '0' or '' (the empty string).

        The statement could be used to 'canonicalize' any false value to the numeric value of 0. If this is the intent of the statement, it is good style.

        I've never used the bit wise version yet in Perl. Probably because I seldom use Perl for any bit manipulation, but I have twiggled bits although that is not Perl's forte!

        This ||= critter can show up in a number of contexts. For me the most common ones are:

        1). Default after regex fails

        my $license_class = ($raw_html =~ m|Class:</td><td class="di">(\w+?) +|)[0]; $license_class ||= "BAD_CLASS";
        The above is a "web HTML" scraper app. One common paradigm would be to assign a default and then call something that will override that default if something is found. Here, the regex will always return something (and undef IS "something"), so I just apply the default as the second step.

        2). Use ||= for managing a cache of prior results:

        ...in some sub.... return ( $hash{$value} ||= expensive_func($value) );
        Here I am automatically caching the results of some expensive_func. This the same as $hash{$value} = $hash{$value} || expensive_func($value);

        Perl is magic in that an undefined value in a hash, like $some_href->{'id'} will evaluate to "false" in an "if" statement. You will get an error if this expression is used in say a print or some math operation and it is undefined.

        Whether you are in case (1) above and know exactly what is gonna happen is something that you have to decide. But, yes using ||= to set a default value is fine style.

        Please consider using the cleaner perl5.10 variant //= if you expect $some_ref->{id} to be nonexistent / not defined. $some_href->{id} //= 0 This makes it explicit that you only want to set id when it was not defined before. Then the truthy, falsy nature of '', 0 and other variants is no longer of concern.

        print+qq(\L@{[ref\&@]}@{['@'x7^'!#2/"!4']});

Log In?
Username:
Password:

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

How do I use this? | Other CB clients
Other Users?
Others scrutinizing the Monastery: (17)
As of 2014-12-18 18:52 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    Is guessing a good strategy for surviving in the IT business?





    Results (59 votes), past polls