Logical Defined-Or

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, EXPR1 // EXPR2 returns the value of EXPR1 if it's defined, otherwise, the value of EXPR2 is returned. (EXPR1 is evaluated in scalar context, EXPR2 in the context of // itself). Usually, this is the same result as defined(EXPR1) ? EXPR1 : EXPR2 (except that the ternary-operator form can be used as a lvalue, while EXPR1 // EXPR2 cannot). This is very useful for providing default values for variables. If you actually want to test if at least one of $x and $y is defined, use defined($x // $y) .

The ||, // and && operators return the last value evaluated (unlike C's || and &&, which return 0 or 1). Thus, a reasonably portable way to find out the home directory might be:

 $home =  $ENV{HOME}
// $ENV{LOGDIR}
// (getpwuid($<))[7]
// die "You're homeless!\n";

In particular, this means that you shouldn't use this for selecting between two aggregates for assignment:

@a = @b || @c;		# this is wrong
@a = scalar(@b) || @c;	# really meant this
@a = @b ? @b : @c;		# this works fine, though

As alternatives to && and || when used for control flow, Perl provides the and and or operators (see below). The short-circuit behavior is identical. The precedence of "and" and "or" is much lower, however, so that you can safely use them after a list operator without the need for parentheses:

    unlink "alpha", "beta", "gamma"
or gripe(), next LINE;

With the C-style operators that would have been written like this:

    unlink("alpha", "beta", "gamma")
|| (gripe(), next LINE);

It would be even more readable to write that this way:

unless(unlink("alpha", "beta", "gamma")) {
    gripe();
    next LINE;
}

Using "or" for assignment is unlikely to do what you want; see below.

doc_perl
2016-12-06 03:21:18
Comments
Leave a Comment

Please login to continue.