package overload;
-our $VERSION = '1.13';
+our $VERSION = '1.18';
+
+%ops = (
+ with_assign => "+ - * / % ** << >> x .",
+ assign => "+= -= *= /= %= **= <<= >>= x= .=",
+ num_comparison => "< <= > >= == !=",
+ '3way_comparison' => "<=> cmp",
+ str_comparison => "lt le gt ge eq ne",
+ binary => '& &= | |= ^ ^=',
+ unary => "neg ! ~",
+ mutators => '++ --',
+ func => "atan2 cos sin exp abs log sqrt int",
+ conversion => 'bool "" 0+ qr',
+ iterators => '<>',
+ filetest => "-X",
+ dereferencing => '${} @{} %{} &{} *{}',
+ matching => '~~',
+ special => 'nomethod fallback =',
+);
+
+my %ops_seen;
+for $category (keys %ops) {
+ $ops_seen{$_}++ for (split /\s+/, $ops{$category});
+}
sub nil {}
sub OVERLOAD {
$package = shift;
my %arg = @_;
+ for (keys %arg) {
+ warn "overload arg '$_' is invalid" unless $ops_seen{$_};
+ }
my ($sub, $fb);
$ {$package . "::OVERLOAD"}{dummy}++; # Register with magic by touching.
$fb = ${$package . "::()"}; # preserve old fallback value RT#68196
$ {$package . "::(" . $_} = $sub;
$sub = \&nil;
}
- #print STDERR "Setting `$ {'package'}::\cO$_' to \\&`$sub'.\n";
+ #print STDERR "Setting '$ {'package'}::\cO$_' to \\&'$sub'.\n";
*{$package . "::(" . $_} = \&{ $sub };
}
}
sub Overloaded {
my $package = shift;
$package = ref $package if ref $package;
- $package->can('()');
+ mycan ($package, '()');
}
sub ov_method {
'qr' => 0x10000, # HINT_NEW_RE
);
-%ops = ( with_assign => "+ - * / % ** << >> x .",
- assign => "+= -= *= /= %= **= <<= >>= x= .=",
- num_comparison => "< <= > >= == !=",
- '3way_comparison'=> "<=> cmp",
- str_comparison => "lt le gt ge eq ne",
- binary => '& &= | |= ^ ^=',
- unary => "neg ! ~",
- mutators => '++ --',
- func => "atan2 cos sin exp abs log sqrt int",
- conversion => 'bool "" 0+ qr',
- iterators => '<>',
- filetest => "-X",
- dereferencing => '${} @{} %{} &{} *{}',
- matching => '~~',
- special => 'nomethod fallback =');
-
use warnings::register;
sub constant {
# Arguments: what, sub
last;
}
elsif (!exists $constants {$_ [0]}) {
- warnings::warnif ("`$_[0]' is not an overloadable type");
+ warnings::warnif ("'$_[0]' is not an overloadable type");
}
elsif (!ref $_ [1] || "$_[1]" !~ /(^|=)CODE\(0x[0-9a-f]+\)$/) {
# Can't use C<ref $_[1] eq "CODE"> above as code references can be
# blessed, and C<ref> would return the package the ref is blessed into.
if (warnings::enabled) {
$_ [1] = "undef" unless defined $_ [1];
- warnings::warn ("`$_[1]' is not a code reference");
+ warnings::warn ("'$_[1]' is not a code reference");
}
}
else {
Exceptions, including additional overloadable operations not
apparent from this hash, are included in the notes which follow.
+A warning is issued if an attempt is made to register an operator not found
+above.
+
=over 5
=item * C<not>
The key C<"~~"> allows you to override the smart matching logic used by
the C<~~> operator and the switch construct (C<given>/C<when>). See
-L<perlsyn/switch> and L<feature>.
+L<perlsyn/Switch Statements> and L<feature>.
Unusually, the overloaded implementation of the smart match operator
does not get full control of the smart match behaviour.
$obj->match(2,0);
$obj->match(3,0);
-Consult the match table in L<perlsyn/"Smart matching in detail"> for
+Consult the match table in L<perlop/"Smartmatch Operator"> for
details of when overloading is invoked.
=item * I<Dereferencing>
There are exceptions to the above rules for dereference operations
(which, if Step 1 fails, always fall back to the normal, built-in
implementations - see Dereferencing), and for C<~~> (which has its
-own set of rules - see L<Matching>).
+own set of rules - see C<Matching> under L</Overloadable Operations>
+above).
Note on Step 7: some operators have a different semantic depending
on the type of their operands.
=head2 Losing Overloading
The restriction for the comparison operation is that even if, for example,
-`C<cmp>' should return a blessed reference, the autogenerated `C<lt>'
+C<cmp> should return a blessed reference, the autogenerated C<lt>
function will produce only a standard logical value based on the
-numerical value of the result of `C<cmp>'. In particular, a working
+numerical value of the result of C<cmp>. In particular, a working
numeric conversion is needed in this case (possibly expressed in terms of
other conversions).
require two_face;
my $seven = two_face->new("vii", 7);
printf "seven=$seven, seven=%d, eight=%d\n", $seven, $seven+1;
- print "seven contains `i'\n" if $seven =~ /i/;
+ print "seven contains 'i'\n" if $seven =~ /i/;
(The second line creates a scalar which has both a string value, and a
numeric value.) This prints:
seven=vii, seven=7, eight=8
- seven contains `i'
+ seven contains 'i'
=head2 Two-face References
my $cnt = $iter;
while ($cnt) {
- $cnt = $cnt - 1; # Mutator `--' not implemented
+ $cnt = $cnt - 1; # Mutator '--' not implemented
$side = (sqrt(1 + $side**2) - 1)/$side;
}
printf "%s=%f\n", $side, $side;
$subr{$op} = eval "sub {shift() $op shift()}";
}
foreach my $op (split " ", "@overload::ops{qw(unary func)}") {
- print "defining `$op'\n";
+ print "defining '$op'\n";
$subr{$op} = eval "sub {$op shift()}";
}
sub FETCH { shift }
sub nop { } # Around a bug
-(the bug is described in L<"BUGS">). One can use this new interface as
+(the bug, fixed in Perl 5.14, is described in L<"BUGS">). One can use this
+new interface as
tie $a, 'symbolic', 3;
tie $b, 'symbolic', 4;
(W) The call to overload::constant contained an odd number of arguments.
The arguments should come in pairs.
-=item `%s' is not an overloadable type
+=item '%s' is not an overloadable type
(W) You tried to overload a constant type the overload package is unaware of.
-=item `%s' is not a code reference
+=item '%s' is not a code reference
(W) The second (fourth, sixth, ...) argument of overload::constant needs
to be a code reference. Either an anonymous subroutine, or a reference
=item *
+Before Perl 5.14, the relation between overloading and tie()ing was broken.
+Overloading is triggered or not basing on the I<previous> class of the
+tie()d variable.
+
+This happened because the presence of overloading was checked
+too early, before any tie()d access was attempted. If the
+class of the value FETCH()ed from the tied variable does not
+change, a simple workaround for code that is to run on older Perl
+versions is to access the value (via C<() = $foo> or some such)
+immediately after tie()ing, so that after this call the I<previous> class
+coincides with the current one.
+
+=item *
+
Barewords are not covered by overloaded string constants.
=back