[tpm] Is there a three-way version of...

John Macdonald john at perlwolf.com
Mon Jun 1 09:54:05 PDT 2009


On Sat, May 30, 2009 at 02:54:13AM -0400, J. Bobby Lopez wrote:
> It basically looks like we're talking about switch statements. An alternate
> method of doing the same thing would be as follows, though I'm not sure how
> expensive it is:
> 
> $a = "";
> $a = $b if $a = "";
> $a = $c if $a = "";
> $a = $d if $a = "";
> ...
> $a = "default" if $a = "";

This has a different meaning - you're testing for empty
string while // tests for undefined.  The empty string is a
defined value.  If would happen in my example below if the
command line had an arg of --foo= instead of --foo=0.

As far as expensive, consider how your version would read if,
instead of $a, you were setting a value nested deep in a hash.
The direct change to your form would be:

    $my{$first}{$second}{option} = undef;
    $my{$first}{$second}{option} = $b
        unless defined $my{$first}{$second}{option};
    $my{$first}{$second}{option} = $c
        unless defined $my{$first}{$second}{option};
    $my{$first}{$second}{option} = $d
        unless defined $my{$first}{$second}{option};
    $my{$first}{$second}{option} = 'default'
        unless defined $my{$first}{$second}{option};

Using a temporary alias into the structure (as Uri suggests
in another message) that gets shorter:

    my $alias = \$my{$first}{$second}{option};
    $alias = undef;
    $alias = $b unless defined $alias;
    $alias = $c unless defined $alias;
    $alias = $d unless defined $alias;
    $alias = 'default' unless defined $alias;

But that's still a lot messier, harder to read, and more
expensive to execute than:

    $my{$first}{$second}{option} = $b // $c // $d // 'default';

> On Fri, May 29, 2009 at 4:43 PM, John Macdonald <john at perlwolf.com> wrote:
> 
> > On Fri, May 29, 2009 at 04:20:48PM -0400, Mike Stok wrote:
> > > As of perl 5.10 (I think) it is the "defined or" operator which only
> > > returns the right hand side if the left hand side is undef, from perlop:
> > >
> > >        C−style Logical Defined‐Or
> > >
> > >        Although it has no direct equivalent in C, Perl’s "//" operator is
> > >        related to its C−style or.  In fact, it’s exactly the same as
> > > "||",
> > >        except that it tests the left hand side’s definedness instead of
> > > its
> > >        truth.  Thus, "$a // $b" is similar to "defined($a) || $b" (except
> > > that
> > >        it returns the value of $a rather than the value of
> > > "defined($a)") and
> > >        is exactly equivalent to "defined($a) ? $a : $b".  This is very
> > > useful
> > >        for providing default values for variables.  If you actually want
> > > to
> > >        test if at least one of $a and $b is defined, use "defined($a //
> > > $b)".
> > >
> > >        The "||", "//" and "&&" operators return the last value evaluated
> > >        (unlike C’s "||" and "&&", which return 0 or 1).
> >
> > This is especially useful for setting a value that can come from
> > multiple optional locations, and using the first one that was
> > actually provided:
> >
> >    $foo = $opt{foo} || $ENV{PROG_FOO} || $rc_opts{foo} || 'default';
> >
> > and, as Mike said, this will still take the first one found even
> > if the explicitly provided value is 0 or ''.  e.g.:
> >
> >    prog --foo=0
> >
> > The || operator would skip this setting (because it's false) and
> > go on to getting the setting of foo from the alternate sources.
> > _______________________________________________
> > toronto-pm mailing list
> > toronto-pm at pm.org
> > http://mail.pm.org/mailman/listinfo/toronto-pm
> >
> 
> 
> 
> -- 
> J. Bobby Lopez
> Web: http://jbldata.com/
> Twitter: http://www.twitter.com/jbobbylopez


More information about the toronto-pm mailing list