Skip to content

perlop: Fixups #23286

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 16 commits into from
May 30, 2025
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
218 changes: 128 additions & 90 deletions pod/perlop.pod
Original file line number Diff line number Diff line change
@@ -18,7 +18,7 @@ means that Perl has two versions of some operators, one for numeric
and one for string comparison. For example S<C<$x == $y>> compares
two numbers for equality, and S<C<$x eq $y>> compares two strings.

There are a few exceptions though: C<x> can be either string
There are a few exceptions though: The operator C<x> can be either string
repetition or list repetition, depending on the type of the left
operand, and C<&>, C<|>, C<^> and C<~> can be either string or numeric bit
operations.
@@ -79,16 +79,16 @@ at all if the short-circuiting means that it's not required for any
comparisons.) This matters if the computation of an interior argument
is expensive or non-deterministic. For example,

if($x < expensive_sub() <= $z) { ...
if ($x < expensive_sub() <= $z) { ...

is not entirely like

if($x < expensive_sub() && expensive_sub() <= $z) { ...
if ($x < expensive_sub() && expensive_sub() <= $z) { ...

but instead closer to

my $tmp = expensive_sub();
if($x < $tmp && $tmp <= $z) { ...
if ($x < $tmp && $tmp <= $z) { ...

in that the subroutine is only called once. However, it's not exactly
like this latter code either, because the chained comparison doesn't
@@ -152,8 +152,9 @@ values only, not array values.
left and
left or xor

In the following sections, these operators are covered in detail, in the
same order in which they appear in the table above.
The following sections cover these operators in detail. Each section
covers all the operators for a single precedence level. The sections
are ordered highest precedence first, same as in the table above.

Many operators can be overloaded for objects. See L<overload>.

@@ -216,14 +217,14 @@ Also parsed as terms are the S<C<do {}>> and S<C<eval {}>> constructs, as
well as subroutine and method calls, and the anonymous
constructors C<[]> and C<{}>.

See also L</Quote and Quote-like Operators> toward the end of this section,
See also L</Quote and Quote-like Operators> below,
as well as L</"I/O Operators">.

=head2 The Arrow Operator
X<arrow> X<dereference> X<< -> >>

"C<< -> >>" is an infix dereference operator, just as it is in C
and C++. If the right side is either a C<[...]>, C<{...}>, or a
and C++. If the right side is one of a C<[...]>, C<{...}>, or a
C<(...)> subscript, then the left side must be either a hard or
symbolic reference to an array, a hash, or a subroutine respectively.
(Or technically speaking, a location capable of holding a hard
@@ -482,7 +483,7 @@ in logical shift zero bits come in from the left.
Either way, the implementation isn't going to generate results larger
than the size of the integer type Perl was built with (32 bits or 64 bits).

Shifting by negative number of bits means the reverse shift: left
Shifting by a negative number of bits means the reverse shift: left
shift becomes right shift, right shift becomes left shift. This is
unlike in C, where negative shift is undefined.

@@ -537,6 +538,25 @@ X<-X> X<filetest> X<operator, filetest>

See also L</"Terms and List Operators (Leftward)">.

=head2 Class Instance Operator
X<isa operator>

Binary C<isa> evaluates to true when the left argument is an object instance of
the class (or a subclass derived from that class) given by the right argument.
If the left argument is not defined, not a blessed object instance, and does
not derive from the class given by the right argument, the operator evaluates
as false. The right argument may give the class either as a bareword or a
scalar expression that yields a string class name:

if ( $obj isa Some::Class ) { ... }

if ( $obj isa "Different::Class" ) { ... }
if ( $obj isa $name_of_class ) { ... }

This feature is available from Perl 5.31.6 onwards when enabled by
C<use feature 'isa'>. This feature is enabled automatically by a
C<use v5.36> (or higher) declaration in the current scope.

=head2 Relational Operators
X<relational operator> X<operator, relational>

@@ -585,6 +605,20 @@ the section L</"Operator Precedence and Associativity">.
Beware that they do not chain with equality operators, which have lower
precedence.

C<"lt">, C<"le">, C<"ge">, C<"gt">, and C<"cmp"> (this last is described
in the L<next section|/Equality Operators>) use the collation (sort)
order specified by the current C<LC_COLLATE> locale if a S<C<use
locale>> form that includes collation is in effect. See L<perllocale>.
Depending on the capabilities of the platform, these can give reasonable
results with Unicode, but the standard C<L<Unicode::Collate>> and
C<L<Unicode::Collate::Locale>> modules offer much more powerful
solutions to collation issues.

For case-insensitive comparisons, look at the L<perlfunc/fc> case-folding
function, available in Perl v5.16 or later:

if ( fc($x) eq fc($y) ) { ... }

=head2 Equality Operators
X<equality> X<equal> X<equals> X<operator, equality>

@@ -631,56 +665,26 @@ Binary C<"cmp"> returns -1, 0, or 1 depending on whether the left
argument is stringwise less than, equal to, or greater than the right
argument.

Here we can see the difference between <=> and cmp,
Here we can see the difference between C<< <=> >> and C<cmp>,

print 10 <=> 2 #prints 1
print 10 cmp 2 #prints -1

(likewise between gt and >, lt and <, etc.)
X<cmp>
(likewise between the relational operators that were described in the
L<previous section|/Relational Operators>: C<gt> and C<< > >>, C<lt> and
C<< < >>, I<etc>.)

Binary C<"~~"> does a smartmatch between its arguments. Smart matching
is described in the next section.
is complicated enough to warrant
L<two subsections|/Smartmatch Operator>, starting just below.
X<~~>

The two-sided ordering operators C<"E<lt>=E<gt>"> and C<"cmp">, and the
smartmatch operator C<"~~">, are non-associative with respect to each
other and with respect to the equality operators of the same precedence.

C<"lt">, C<"le">, C<"ge">, C<"gt"> and C<"cmp"> use the collation (sort)
order specified by the current C<LC_COLLATE> locale if a S<C<use
locale>> form that includes collation is in effect. See L<perllocale>.
Do not mix these with Unicode,
only use them with legacy 8-bit locale encodings.
The standard C<L<Unicode::Collate>> and
C<L<Unicode::Collate::Locale>> modules offer much more powerful
solutions to collation issues.

For case-insensitive comparisons, look at the L<perlfunc/fc> case-folding
function, available in Perl v5.16 or later:

if ( fc($x) eq fc($y) ) { ... }

=head2 Class Instance Operator
X<isa operator>

Binary C<isa> evaluates to true when the left argument is an object instance of
the class (or a subclass derived from that class) given by the right argument.
If the left argument is not defined, not a blessed object instance, nor does
not derive from the class given by the right argument, the operator evaluates
as false. The right argument may give the class either as a bareword or a
scalar expression that yields a string class name:

if( $obj isa Some::Class ) { ... }

if( $obj isa "Different::Class" ) { ... }
if( $obj isa $name_of_class ) { ... }

This feature is available from Perl 5.31.6 onwards when enabled by
C<use feature 'isa'>. This feature is enabled automatically by a
C<use v5.36> (or higher) declaration in the current scope.

=head2 Smartmatch Operator
=head3 Smartmatch Operator

First available in Perl 5.10.1 (the 5.10.0 version behaved differently),
binary C<~~> does a "smartmatch" between its arguments. This is mostly
@@ -987,9 +991,13 @@ C<"experimental::bitwise"> category.
X<operator, bitwise, or> X<bitwise or> X<|> X<operator, bitwise, xor>
X<bitwise xor> X<^>

Binary C<"|"> returns its operands ORed together bit by bit.
Binary C<"|"> returns its operands ORed together bit by bit. If both
corresponding bits are 0, the resulting bit is 0; if either is 1, the result is
1.

Binary C<"^"> returns its operands XORed together bit by bit.
Binary C<"^"> returns its operands XORed together bit by bit. If both
corresponding bits are 0 or both are 1, the resulting bit is 0; if just
one is 1, the result is 1.

Although no warning is currently raised, the results are not well
defined when these operations are performed on operands that aren't either
@@ -1014,24 +1022,52 @@ if the left operand is false, the right operand is not even evaluated.
Scalar or list context propagates down to the right operand if it
is evaluated.

=head2 C-style Logical Or
C<&&> returns the last value evaluated (unlike C's C<&&>, which returns
0 or 1).

As an alternative to C<&&> when used for control flow, Perl provides the
C<and> operator (see L<below|/Logical And>).
The short-circuit behavior is identical. The precedence of C<"and"> is
much lower, however, so that you can safely use it after a list operator
without the need for parentheses.

=head2 C-style Logical Or, Xor, and Defined Or
X<||> X<operator, logical, or>
X<^^> X<operator, logical, xor>
X<//> X<operator, logical, defined-or>

Binary C<"||"> performs a short-circuit logical OR operation. That is,
if the left operand is true, the right operand is not even evaluated.
Scalar or list context propagates down to the right operand if it
is evaluated.
does get evaluated.

=head2 C-style Logical Xor
X<^^> X<operator, logical, xor>
As an alternative to C<||> when used for control flow, Perl provides the
C<or> operator (L<see below|/Logical or and Exclusive Or>).
The short-circuit behavior is identical. The precedence of C<"or"> is
much lower, however, so that you can safely use it after a list operator
without the need for parentheses:

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

With the C-style operator 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 C<"or"> for assignment is unlikely to do what you want; see below.

Binary C<"^^"> performs a logical XOR operation. Both operands are
evaluated and the result is true only if exactly one of the operands is true.
Scalar or list context propagates down to the right operand.

=head2 Logical Defined-Or
X<//> X<operator, logical, defined-or>

Although it has no direct equivalent in C, Perl's C<//> operator is related
to its C-style "or". In fact, it's exactly the same as C<||>, except that it
tests the left hand side's definedness instead of its truth. Thus,
@@ -1045,8 +1081,8 @@ cannot). This is very useful for
providing default values for variables. If you actually want to test if
at least one of C<$x> and C<$y> is defined, use S<C<defined($x // $y)>>.

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

$home = $ENV{HOME}
@@ -1061,29 +1097,6 @@ for selecting between two aggregates for assignment:
@a = scalar(@b) || @c; # because it really means this.
@a = @b ? @b : @c; # This works fine, though.

As alternatives to C<&&> and C<||> when used for
control flow, Perl provides the C<and> and C<or> operators (see below).
The short-circuit behavior is identical. The precedence of C<"and">
and C<"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 C<"or"> for assignment is unlikely to do what you want; see below.

=head2 Range Operators
X<operator, range> X<range> X<..> X<...>

@@ -1489,13 +1502,14 @@ precedence. This means that it short-circuits: the right
expression is evaluated only if the left expression is true.

=head2 Logical or and Exclusive Or
X<operator, logical, or> X<operator, logical, xor>
X<operator, logical, exclusive or>
X<or> X<xor>
X<operator, logical, or> X<or>
X<operator, logical, xor> X<operator, logical, exclusive or> X<xor>

There is no low precedence operator for defined-OR.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This feels slightly better at the end of this section, as an "addendum," in my opinion at least

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

How would that read? I think the current situation is that it gets lost

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

My feeling is that people would more likely go to this section of the documentation to find out about the or and xor operators, more than to search for a low precedence defined-or, but I have no objections to putting that sentence first either.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@Grinnz, I agree that that is why they would come here; but I moved the sentence because I thought that point would be lost where it was, and it's not really a problem to have it moved.

Now you say you don't object to moving the sentence. What changes need to be made, then?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Totally up to you, just giving my opinion on it

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm open to suggestions for a better way


Binary C<"or"> returns the logical disjunction of the two surrounding
expressions. It's equivalent to C<||> except for the very low precedence.
This makes it useful for control flow:
Binary C<"or"> returns the logical inclusive disjunction of the two
surrounding expressions. It's equivalent to C<||> except for it having
very low precedence. This makes it useful for control flow:

print FH $data or die "Can't write to FH: $!";

@@ -1517,10 +1531,16 @@ takes higher precedence.

Then again, you could always use parentheses.

Binary C<"xor"> returns the exclusive-OR of the two surrounding expressions.
It cannot short-circuit (of course).
Binary C<"xor"> returns the logical exclusive disjunction of the two
surrounding expressions. That means it returns C<true> if either, but
not both, are true. It's equivalent to C<^^> except for it having very
low precedence. It cannot short-circuit (of course). It tends to be
used to verify that two mutually-exclusive conditions are actually
mutually exclusive. For example, in Perl's test suite, we might want to
test that a regular expression pattern can't both match and not match,
for otherwise it would be a bug in our pattern matching code.

There is no low precedence operator for defined-OR.
($x =~ qr/$pat/ xor $x !~ qr/$pat/) or die;

=head2 C Operators Missing From Perl
X<operator, missing from perl> X<&> X<*>
@@ -1583,7 +1603,7 @@ is the same as

Note, however, that this does not always work for quoting Perl code:

$s = q{ if($x eq "}") ... }; # WRONG
$s = q{ if ($x eq "}") ... }; # WRONG

is a syntax error. The C<L<Text::Balanced>> module (standard as of v5.8,
and from CPAN before then) is able to do this properly.
@@ -3836,6 +3856,24 @@ Here is a short, but incomplete summary:

Choose wisely.

=head2 C-style Logical Or

This section has been superceded by
L</C-style Logical Or, Xor, and Defined Or>. The heading is retained
only to prevent breaking any pre-existing links to it from outside.

=head2 C-style Logical Xor

This section has been superceded by
L</C-style Logical Or, Xor, and Defined Or>. The heading is retained
only to prevent breaking any pre-existing links to it from outside.

=head2 Logical Defined-Or

This section has been superceded by
L</C-style Logical Or, Xor, and Defined Or>. The heading is retained
only to prevent breaking any pre-existing links to it from outside.

=head1 APPENDIX

=head2 List of Extra Paired Delimiters