=head1 AUTOLOAD Z Perl does not require you to declare every function before you call it. Perl will happily attempt to call a function even if it doesn't exist. Consider the program: =begin programlisting use Modern::Perl; bake_pie( filling => 'apple' ); =end programlisting When you run it, Perl will throw an exception due to the call to the undefined function C. Now add a function called C: =begin programlisting sub AUTOLOAD {} =end programlisting When you run the program now, nothing obvious will happen. Perl will call a function named C in a package--if it exists--whenever normal dispatch fails. Change the C to emit a message to demonstrate that it gets called: =begin programlisting sub AUTOLOAD { B } =end programlisting X> The C function receives the arguments passed to the undefined function in C<@_> and the fully-qualified I of the undefined function in the package global C<$AUTOLOAD> (here, C): =begin programlisting sub AUTOLOAD { B # pretty-print the arguments local $" = ', '; say "In AUTOLOAD(@_) B!" } =end programlisting Extract the method name with a regular expression (L): =begin programlisting sub AUTOLOAD { B # pretty-print the arguments local $" = ', '; say "In AUTOLOAD(@_) B!" } =end programlisting Whatever C returns, the original call receives: =begin programlisting say secret_tangent( -1 ); sub AUTOLOAD { return 'mu' } =end programlisting So far, these examples have merely intercepted calls to undefined functions. You have other options. =head2 Redispatching Methods in AUTOLOAD() X; redispatch> X; delegation> X X X X A common pattern in OO programming (L) is to I or I certain methods from one object to another. A logging proxy can help with debugging: =begin programlisting package Proxy::Log; # constructor blesses reference to a scalar sub AUTOLOAD { my ($name) = our $AUTOLOAD =~ /::(\w+)$/; Log::method_call( $name, @_ ); my $self = shift; return $$self->$name( @_ ); } =end programlisting This C extracts the name of the undefined method. Then it dereferences the proxied object from a blessed scalar reference, logs the method call, then invokes that method on the proxied object with the provided parameters. =head2 Generating Code in AUTOLOAD() X; code installation> This double dispatch is easy to write but inefficient. Every method call on the proxy must fail normal dispatch to end up in C. Pay that penalty only once by installing new methods into the proxy class as the program needs them: =begin programlisting sub AUTOLOAD { my ($name) = our $AUTOLOAD =~ /::(\w+)$/; my $method = sub { ... }; B B<*{ $AUTOLOAD } = $method;> return $method->( @_ ); } =end programlisting The body of the previous C has become a closure (L) bound over the I of the undefined method. Installing that closure in the appropriate symbol table allows all subsequent dispatch to that method to find the created closure (and avoid C). This code finally invokes the method directly and returns the result. Though this approach is cleaner and almost always more transparent than handling the behavior directly in C, the code I by C may see C in its C list. While it may violate encapsulation to care that this occurs, leaking the details of I an object provides a method may also violate encapsulation. X X; tailcall> Some code uses a tailcall (L) to I the current invocation of C with a call to the destination method: =begin programlisting sub AUTOLOAD { my ($name) = our $AUTOLOAD =~ /::(\w+)$/; my $method = sub { ... } no strict 'refs'; *{ $AUTOLOAD } = $method; B } =end programlisting This has the same effect as invoking C<$method> directly, except that C will no longer appear in the list of calls available from C, so it looks like normal method dispatch occurred. =head2 Drawbacks of AUTOLOAD Z X; drawbacks> X> X> X pragma> X> X C can be useful, though it is difficult to use properly. The naEve approach to generating methods at runtime means that the C method will not report the right information about the capabilities of objects and classes. The easiest solution is to predeclare all functions you plan to C with the C pragma: =begin programlisting use subs qw( red green blue ochre teal ); =end programlisting =begin tip Now You See Them Forward declarations are useful only in the two rare cases of attributes (L) and autoloading (L). =end tip That technique documents your intent well, but requires you to maintain a static list of functions or methods. Overriding C (L) sometimes works better: =begin programlisting sub can { my ($self, $method) = @_; # use results of parent can() my $meth_ref = $self->SUPER::can( $method ); return $meth_ref if $meth_ref; # add some filter here return unless $self->should_generate( $method ); $meth_ref = sub { ... }; no strict 'refs'; return *{ $method } = $meth_ref; } sub AUTOLOAD { my ($self) = @_; my ($name) = our $AUTOLOAD =~ /::(\w+)$/;> return unless my $meth_ref = $self->can( $name ); goto &$meth_ref; } =end programlisting C is a big hammer; it can catch functions and methods you had no intention of autoloading, such as C, the destructor of objects. If you write a C method with no implementation, Perl will happily dispatch to it instead of C: =begin programlisting # skip AUTOLOAD() sub DESTROY {} =end programlisting =begin tip A Very Special Method The special methods C, C, and C never go through C. =end tip If you mix functions and methods in a single namespace which inherits from another package which provides its own C, you may see the strange error: =begin screen Use of inherited AUTOLOAD for non-method I() is deprecated =end screen If this happens to you, simplify your code; you've called a function which does not exist in a package which inherits from a class which contains its own C. The problem compounds in several ways: mixing functions and methods in a single namespace is often a design flaw, inheritance and C get complex very quickly, and reasoning about code when you don't know what methods objects provide is difficult. C is useful for quick and dirty programming, but robust code avoids it.