1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135
|
# You may distribute under the terms of either the GNU General Public License
# or the Artistic License (the same terms as Perl itself)
#
# (C) Paul Evans, 2021-2024 -- leonerd@leonerd.org.uk
package Syntax::Operator::In 0.10;
use v5.14;
use warnings;
use Carp;
require XSLoader;
XSLoader::load( __PACKAGE__, our $VERSION );
=head1 NAME
C<Syntax::Operator::In> - infix element-of-list meta-operator
=head1 SYNOPSIS
On Perl v5.38 or later:
use Syntax::Operator::In;
if($x in:eq @some_strings) {
say "x is one of the given strings";
}
=head1 DESCRIPTION
This module provides an infix meta-operator that implements a element-of-list
test on either strings or numbers.
Support for custom infix operators was added in the Perl 5.37.x development
cycle and is available from development release v5.37.7 onwards, and therefore
in Perl v5.38 onwards. The documentation of L<XS::Parse::Infix>
describes the situation in more detail.
While Perl versions before this do not support custom infix operators, they
can still be used via C<XS::Parse::Infix> and hence L<XS::Parse::Keyword>.
Custom keywords which attempt to parse operator syntax may be able to use
these.
For operators that already specialize on string or numerical equality, see
instead L<Syntax::Operator::Elem>.
=cut
sub import
{
my $pkg = shift;
my $caller = caller;
$pkg->import_into( $caller, @_ );
}
sub unimport
{
my $pkg = shift;
my $caller = caller;
$pkg->unimport_into( $caller, @_ );
}
sub import_into { shift->apply( 1, @_ ) }
sub unimport_into { shift->apply( 0, @_ ) }
sub apply
{
my $pkg = shift;
my ( $on, $caller, @syms ) = @_;
@syms or @syms = qw( in );
$pkg->XS::Parse::Infix::apply_infix( $on, \@syms, qw( in ) );
croak "Unrecognised import symbols @syms" if @syms;
}
=head1 OPERATORS
=head2 in
my $present = $lhs in:OP @rhs;
my $present = $lhs in<OP> @rhs;
Yields true if the value on the lefhand side is equal to any of the values in
the list on the right, according to some equality test operator C<OP>.
This test operator must be either C<eq> for string match, or C<==> for number
match, or any other custom infix operator that is registered in the
C<XPI_CLS_EQUALITY> classification.
There are currently two accepted forms of the syntax for this operator, using
either a prefix colon or a circumfix pair of angle-brackets. They are entirely
identical in semantics, differing only in the surface-level syntax to notate
them. This is because I'm still entirely undecided on which notation is better
in terms of readable neatness, flexibility, parsing ambiguity and so on. This
is somewhat of an experiment to see which will eventually win.
=cut
=head1 TODO
=over 4
=item *
Improve runtime performance of compiletime-constant sets of strings, by
detecting when the RHS contains string constants and convert it into a hash
lookup.
=item *
Consider cross-module integration with L<Syntax::Keyword::Match>, permitting
match($val : elem) {
case(@arr_of_strings) { ... }
}
Or perhaps this would be too weird, and maybe C<match/case> should have an
"any-of" list/array matching ability itself. See also
L<https://rt.cpan.org/Ticket/Display.html?id=143482>.
=back
=head1 AUTHOR
Paul Evans <leonerd@leonerd.org.uk>
=cut
0x55AA;
|