in reply to Re: What is the difference between |= and ||=?
in thread What is the difference between |= and ||=?

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?

Replies are listed 'Best First'.
Re^3: What is the difference between |= and ||=?
by ikegami (Patriarch) on Apr 07, 2009 at 16:19 UTC

    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?

      It's undef because the hash reference is a value returned from an SQL query. If no rows are selected (for instance), then it's possible for the 'id' value to be undef. And when I perform some math operation (as noted by Marshall below), the warning is triggered. I could wrap the math operation code around a conditional to suppress the warning:

      if ($some_href->{id}) { if ($some_href->{id} > 0) { do_something(); } }
      But I'm not sure if that's better than using ||=.
        If no row was selected, then whose id is that? Sure smells fishy.
Re^3: What is the difference between |= and ||=?
by AnomalousMonk (Archbishop) on Apr 07, 2009 at 16:24 UTC
    $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.

Re^3: What is the difference between |= and ||=?
by Marshall (Canon) on Apr 07, 2009 at 21:11 UTC
    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.

Re^3: What is the difference between |= and ||=?
by codeacrobat (Chaplain) on Apr 07, 2009 at 22:05 UTC
    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']});
      Please don't, unless you can be sure that all your users are on perl 5.10. Remember, 5.10 is still very new, and given that it's 5.10.*0* lots of people will be ignoring it and waiting for 5.10.1, as .0 releases of software are commonly seen as being not really ready for serious use.

      Ah, I see. Thanks :)

      It's exactly what I need in a few cases. But...hm...the shared server isn't using 5.10 :(