traveler has asked for the wisdom of the Perl Monks concerning the following question:

All, I find I am using these constructs a lot in my code: $a = exists $foo->{a} ? $foo->{a} : $default_for_a ; and $foo = defined $bar ? $bar : $default_for_foo;. Is there a better way? It would seem as though this is common enough that ther might be a shortcut.

--traveler

Replies are listed 'Best First'.
Re: Effecient shortcut for ?:
by samtregar (Abbot) on Aug 07, 2002 at 17:51 UTC
    No, but there will be in Perl 6 (or possibly Perl 5.10):

    $foo //= $bar;

    The // and //= operators will behave like || but will test for defined() rather than for truth.

    -sam

Re: Effecient shortcut for ?:
by PodMaster (Abbot) on Aug 07, 2002 at 17:50 UTC
    I don't believe efficiency comes into play, but, your 2nd example "could" be rewritten as
    $foo = defined $bar ? bar : $default_for_foo; ## could be written as, but remember, that 0 is false $foo = $bar; $foo ||= $default_for_foo;

    ____________________________________________________
    ** The Third rule of perl club is a statement of fact: pod is sexy.

      These two are not exactly the same... they will behave differently if $bar is defined but has a non-true value (like 0). That's because the || operator tests for truth, while the much-to-be-desired // operator (in Perl6) will test for defined-ness. So in Perl6, you could write it as:
      $foo = $bar; $foo //= $default_for_foo;
      or, I imagine, like this:
      $foo = $bar // $default_for_foo;

      -- Mike

      --
      just,my${.02}

(tye)Re: Effecient shortcut for ?:
by tye (Sage) on Aug 07, 2002 at 21:48 UTC

    While waiting for the speculated "defined" version of "||", I wrote def -- Deal nicely with undefined values. That simplifies your second case:     $foo = def( $bar, $default_for_foo ); Throwing together something for exists I came up with this:     $a = has( a=>$hashref, $default_for_a ); I replaced $foo with $hashref in my example above.

    Here is what has() looks like:

    sub has { my( $key, $hv, $val, $force )= @_; if( exists $hv->{$key} ) { $val= $hv->{$key}; } elsif( ! defined wantarray || $force ) { $hv->{$key}= $val; } return $val; }
    Petruchio has been talking about creating a module to provide fairly simple tools like this that allow you to replace idiomatic constructs with simpler (more natural) constructs. I'll think has() and def() are worth including. (:

            - tye (but my friends call me "Tye")
Re: Effecient shortcut for ?:
by dws (Chancellor) on Aug 07, 2002 at 18:25 UTC
    Another approach to the ones above is to establish defaults when you set up the hash. This is common when creating objects.
    sub new { my $pkg = shift; my $self = { a => $default_for_a, @_ }; bless $self, $pkg; }
    If you don't specify a binding for "a" when you create the instance, you get the default. If do specify a binding, as with   my $foo = new Foo(a => 47); then the default is overlaid.

      I do this occasionally, when establishing quick defaults. Testing revealed that the last defined key/value pair for a given hash is the one that is used. Is this documented anywhere?
      my $self = { %defaults, @_ };
        As far as I know, it's only documented in the same sense as this bit of code:
        my $x; $x = 1; $x = 2;
Re: Effecient shortcut for ?:
by kvale (Monsignor) on Aug 07, 2002 at 17:50 UTC
    There is some talk of adding a shortcut for this in Perl6, but currently your code is a reasonable way to go about incorporating default values.

    -Mark