# 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.