# In the SomeThing module: package SomeThing; use overload '+' => \&myadd, '-' => \&mysub; # In your other code: use SomeThing; $a = SomeThing->new(57); $b=5+$a; if (overload::Overloaded $b) {...} # is $b subject to overloading? $strval = overload::StrVal $b;
Caveat Scriptor: This interface is the subject of ongoing research. Feel free to play with it, but don't be too surprised if the interface changes subtly (or not so subtly) as it is developed further. If you rely on it for a mission-critical application, please be sure to write some good regression tests. (Or perhaps in this case we should call them "progression" tests.)
This module allows you to substitute class methods or your own subroutines for standard Perl operators. For example, the code:
package Number; use overload "+" => \&add, "*=" => "muas";
declares function add()
for addition, and method
muas()
in the Number class (or one of its base classes) for
the assignment form *=
of multiplication.
Arguments to use overload
come in key/value pairs. Legal values
are values permitted inside a &{ ... }
call, so the name of a
subroutine, a reference to a subroutine, or an anonymous subroutine will
all work. Legal keys are listed below.
The subroutine add()
will be called to execute
$a+$b
if $a
is a reference to an object
blessed into the package Number
, or if $a
is not an object from a package with overloaded addition, but
$b
is a reference to a Number
. It can
also be called in other situations, like $a+=7
, or
$a++
. See the section on "Autogeneration".
The functions specified with the use overload
directive are
typically called with three arguments. (See the "No Method" section later in
this chapter for the four-argument case.) If the corresponding operation is
binary, then the first two arguments are the two arguments of the operation.
However, due to general object-calling conventions, the first argument should
always be an object in the package, so in the situation of
7+$a
, the order of the arguments gets interchanged before the
method is called. It probably does not matter when implementing the addition
method, but whether the arguments are reversed is vital to the subtraction
method. The method can query this information by examining the third argument,
which can take three different values:
The order of arguments is as in the current operation.
The arguments are reversed.
The current operation is an assignment variant (as in
$a+=7
), but the usual function is called instead. This additional
information can be used to generate some optimizations.
Unary operations are considered binary operations with the second argument being
undef. Thus the function that overloads
{"++"}
is called with arguments ($a, undef,
"")
when $a
++ is executed.
The following operations can be specified with use overload
:
Arithmetic operations
+ - * / % ** << >> x . += -= *= /= %= **= <<= >>= x= .=
For these operations a substituted non-assignment variant can be called if
the assignment variant is not available. Methods for operations "+
",
"-
", "+=
", and "-=
" can be called to automatically generate
increment and decrement methods. The operation "-
" can be used to
autogenerate missing methods for unary minus or abs()
.
Comparison operations
< <= > >= == != <=> lt le gt ge eq ne cmp
The <=>
operator can substitute for any of the other numeric compare
operators, and cmp can substitute for any missing string compare
operators. When using sort on
arrays, cmp
is used to compare values subject to use overload
.
& ^ | neg ! ~
"neg
" stands for unary minus. If the method for neg
is not
specified, it can be autogenerated using the method for subtraction.
Increment and decrement
++ --
If undefined, addition and subtraction methods can be used instead. These operations are called both in prefix and postfix form.
Transcendental functions
atan2 cos sin exp abs log sqrt
If abs
is unavailable, it can be autogenerated using methods
for "<
" or "<=>
" combined with either unary minus or subtraction.
Boolean, string and numeric conversion
bool "" 0+
(Yes, that really is two double-quotes in a row.) If one or two of these
operations are unavailable, the remaining ones can be used instead.
bool
is used in the flow control operators (like while and if) and for the
trinary "?:
" operation. These functions can return any
arbitrary Perl value. If the corresponding operation for this value is
overloaded, too, then that operation will be called again with this value.
Special
nomethod fallback =
The following sections provide explanation.
Three keys are recognized by Perl that are not covered by the above
descriptions: "nomethod
",
"fallback
", and
"=
".
"nomethod
" should be followed by a reference to a
function of four parameters. If defined, it is called when the overloading
mechanism cannot find a method for some operation. The first three arguments of
this function coincide with the arguments for the corresponding method if it
were found; the fourth argument is the symbol corresponding to the missing
method. If several methods are tried, the last one is used.
For example,
1-$a
can be equivalent to:
&nomethodMethod($a, 1, 1, "-")
if the pair "nomethod" => "nomethodMethod"
was specified in the use
overload
directive.
If some operation cannot be resolved and there is no function assigned to
"nomethod
", then an exception will be raised via
die unless
"fallback
" was specified as a key in a
use overload
directive.
The "fallback
" key governs what to do if a method for a
particular operation is not found. Three different cases are possible depending
on the value of "fallback
":
Perl tries to use a substituted method (see the section later on
"Autogeneration". If this fails, it then tries to call the method
specified for "nomethod
"; if missing, an exception will be
raised.
The same as for the undefined value, but no exception is raised. Instead,
Perl silently reverts to what it would have done were there no use
overload
present.
No autogeneration is tried. Perl tries to call the method specified
for "nomethod
", and if this is missing, raises an exception.
The value for "=
" is a reference to a function with three
arguments; that is, it looks like the other values in use
overload
. However, it does not overload the Perl assignment
operator. This would rub Camel hair the wrong way.
This operation is called when a mutator is applied to a reference that shares its object with some other reference, such as:
$a=$b; $a++;
In order to change $a
but not $b
, a copy
of $$a
is made, and $a
is assigned a
reference to this new object. This operation is done during execution of the
$a++
, and not during the assignment, (so before the increment
$$a
coincides with $$b
). This is only
done if ++
is expressed via a method for
"++
" or "+=
".
Note that if this operation is expressed via "+
" (a nonmutator):
$a=$b; $a=$a+1;
then $a
does not reference a new copy of $$a
, since
$$a
does not
appear as an lvalue when the above code is executed.
If the copy constructor is required during the execution of some mutator, but a
method for "=
" was not specified, it can be
autogenerated as a string copy if the object is a plain scalar.
As an example, the actually executed code for:
$a=$b; # Something else which does not modify $a or $b... ++$a;
may be:
$a=$b; # Something else which does not modify $a or $b... $a = $a->clone(undef, ""); $a->incr(undef, "");
This assumes $b
is subject to overloading,
"++
" was overloaded with
\&incr
, and "=
" was
overloaded with \&clone
.
If a method for an operation is not found, and the value for
"fallback
" is true or undefined, Perl tries to
autogenerate a substitute method for the missing operation based on the defined
operations. Autogenerated method substitutions are possible for the following
operations:
$a+=$b
can use the method for
"+
" if the method for
"+=
" is not defined.
String, numeric, and Boolean conversion are calculated in terms of one another if not all of them are defined.
The ++$a
operation can be expressed in terms of
$a+=1
or $a+1
, and
$a--
in terms of $a-=1
and $a-1
.
abs($a)
Can be expressed in terms of $a<0
and -$a
(or 0-$a
).
Can be expressed in terms of subtraction.
Can be expressed in terms of string conversion.
Can be expressed in terms of its three-valued counterpart: either
<=>
or cmp
:
<, >, <=, >=, ==, != in terms of <=> lt, gt, le, ge, eq, ne in terms of cmp
Can be expressed in terms of an assignment to the dereferenced value if this value is a scalar and not a reference.
WARNING: One restriction for the comparison operation is that even if, for example,
cmp
returns a blessed reference, the autogeneratedlt
function will produce only a standard logical value based on the numerical value of the result ofcmp
. In particular, a working numeric conversion is needed in this case (possibly expressed in terms of other conversions).Similarly,
.=
andx=
operators lose their overloaded properties if the string conversion substitution is applied.When you chop an object that is subject to overloaded operations, the object is promoted to a string and its overloading properties are lost. The same can happen with other operations as well.
Since all use directives are executed at compile-time, the only way to change overloading during run-time is:
eval 'use overload "+" => \&addmethod';
You can also say:
eval 'no overload "+", "--", "<="';
although the use of these constructs during run-time is questionable.
The overload
module provides the following public functions:
When Perl is run with the -Do
switch or its equivalent, overloading
induces diagnostic messages.
Because it is used for overloading, the per-package associative array
%OVERLOAD
now has a special meaning in Perl.
Overloading is not yet inherited via the @ISA tree, though individual methods may be.