Skip to content
Browse files

Fixed line and page breaking for 2014 edition.

  • Loading branch information...
1 parent d02ff9c commit 4d33f05b7e8a00734c53b0c15eac2918dd0a36aa @chromatic committed Jan 30, 2014
View
2 CREDITS
@@ -150,7 +150,7 @@ E: deeelwy@yahoo.com
N: Marko Zagozen
E: ?
-N: Alexander Scott-Johns
+N: Alex-ander Scott-Johns
E: alexander.scott.johns@googlemail.com
N: Larry Wall
View
13 sections/anonymous_functions.pod
@@ -68,11 +68,9 @@ named function, such as to declare the dispatch table's functions in place:
=begin tip Defensive Dispatch
-This dispatch table offers some degree of security; only those functions mapped
-within the table are available for users to call. If your dispatch function
-blindly assumed that the string given as the name of the operator corresponded
-directly to the name of a function to call, a malicious user could conceivably
-call any function in any other namespace by passing
+Only those functions within this dispatch table are available for users to
+call. If your dispatch function used a user-provided string as the literal name
+of functions, a malicious user could call any function anywhere by passing
C<'Internal::Functions::malicious_function'>.
=end tip
@@ -103,9 +101,8 @@ X<anonymous functions; names>
X<CPAN; C<Sub::Identify>>
-Given a reference to a function, you can determine whether the function is
-named or anonymous with introspectionN<... or C<sub_name> from the CPAN module
-C<Sub::Identify>.>:
+Use introspectionN<See also C<sub_name> from the CPAN module
+C<Sub::Identify>.>: to determine whether a function is named or anonymous:
=begin programlisting
View
17 sections/attributes.pod
@@ -10,8 +10,6 @@ Attribute declaration syntax is awkward, and using attributes effectively is
more art than science. Most programs never use them, but when used well they
offer clarity and maintenance benefits.
-=head2 Using Attributes
-
A simple attribute is a colon-preceded identifier attached to a declaration:
=begin programlisting
@@ -29,10 +27,13 @@ the appropriate handlers do not exist, Perl will throw a compile-time
exception.
X<CPAN; C<Test::Class>>
+X<Catalyst>
+X<CPAN; C<Catalyst>>
Attributes may include a list of parameters. Perl treats these parameters as
-lists of constant strings. Yes, strings. The C<Test::Class> module from the
-CPAN uses such parametric arguments to good effect:
+lists of constant strings. The C<Test::Class> module from the CPAN uses such
+parametric arguments to good effectN<See the Catalyst web framework for
+another, different, example.>:
=begin programlisting
@@ -57,14 +58,6 @@ other classes do their work. Otherwise a test class might have only one method
named C<setup> and one named C<teardown> and would have to do everything there,
then call the parent methods, and so on.
-=begin tip Practical Attributes
-
-X<Catalyst>
-
-The Catalyst web framework also uses attributes to determine the visibility and behavior of methods within web applications.
-
-=end tip
-
=head2 Drawbacks of Attributes
X<pragmas; C<attributes>>
View
38 sections/autoload.pod
@@ -27,23 +27,20 @@ Now add a function called C<AUTOLOAD()>:
When you run the program now, nothing obvious will happen. Perl will call a
function named C<AUTOLOAD()> in a package--if it exists--whenever normal
-dispatch fails. Change the C<AUTOLOAD()> to emit a message:
+dispatch fails. Change the C<AUTOLOAD()> to emit a message to demonstrate that
+it gets called:
=begin programlisting
sub AUTOLOAD { B<say 'In AUTOLOAD()!'> }
=end programlisting
-... to demonstrate that it gets called.
-
-=head2 Basic Features of AUTOLOAD
-
X<C<$AUTOLOAD>>
The C<AUTOLOAD()> function receives the arguments passed to the undefined
-function in C<@_> as usual. The I<name> of the undefined function is available
-in the package global C<$AUTOLOAD>. Manipulate these arguments as you like:
+function in C<@_> and the fully-qualified I<name> of the undefined function in
+the package global C<$AUTOLOAD> (here, C<main::bake_pie>):
=begin programlisting
@@ -58,10 +55,7 @@ in the package global C<$AUTOLOAD>. Manipulate these arguments as you like:
=end programlisting
-The C<our> declaration (L<our>) constrains the scope of C<$AUTOLOAD> to the
-function body. This variable contains the fully-qualified name of the undefined
-function (in this case, C<main::bake_pie>). Extract the method name with a
-regular expression (L<regex>):
+Extract the method name with a regular expression (L<regex>):
=begin programlisting
@@ -106,7 +100,7 @@ former. A logging proxy can help with debugging:
package Proxy::Log;
- # constructor defined but not shown
+ # constructor blesses reference to a scalar
sub AUTOLOAD
{
@@ -137,15 +131,8 @@ them:
sub AUTOLOAD
{
- B<my ($name) = our $AUTOLOAD =~ /::(\w+)$/;>
-
- my $method = sub
- {
- Log::method_call( $name, @_ );
-
- my $self = shift;
- return $$self->$name( @_ );
- }
+ my ($name) = our $AUTOLOAD =~ /::(\w+)$/;
+ my $method = sub { ... };
B<no strict 'refs';>
B<*{ $AUTOLOAD } = $method;>
@@ -162,10 +149,9 @@ method directly and returns the result.
Though this approach is cleaner and almost always more transparent than
handling the behavior directly in C<AUTOLOAD()>, the code I<called> by
-C<AUTOLOAD()> may detect that dispatch has gone through C<AUTOLOAD()>. In
-short, C<caller()> will reflect the double-dispatch of both techniques shown so
-far. While it may violate encapsulation to care that this occurs, leaking the
-details of I<how> an object provides a method may also violate encapsulation.
+C<AUTOLOAD()> may see C<AUTOLOAD()> in its C<caller()> list. While it may
+violate encapsulation to care that this occurs, leaking the details of I<how>
+an object provides a method may also violate encapsulation.
X<tailcalls>
X<C<goto>; tailcall>
@@ -177,7 +163,7 @@ of C<AUTOLOAD()> with a call to the destination method:
sub AUTOLOAD
{
- B<my ($name) = our $AUTOLOAD =~ /::(\w+)$/;>
+ my ($name) = our $AUTOLOAD =~ /::(\w+)$/;
my $method = sub { ... }
no strict 'refs';
View
9 sections/automatic_dereferencing.pod
@@ -32,11 +32,10 @@ X<builtins; C<each>>
The same goes for the array operators C<pop>, C<shift>, C<unshift>, C<splice>,
C<keys>, C<values>, and C<each> and the hash operators C<keys>, C<values>, and
-C<each>.
-
-If the reference provided is not of the proper type--if it does not dereference
-properly--Perl will throw an exception. While this may seem more dangerous than
-explicitly dereferencing references directly, it is in fact the same behavior:
+C<each>. If the reference provided is not of the proper type--if it does not
+dereference properly--Perl will throw an exception. While this may seem more
+dangerous than explicitly dereferencing references directly, it is in fact the
+same behavior:
=begin programlisting
View
20 sections/barewords.pod
@@ -140,16 +140,6 @@ No matter how cautiously you code, barewords still produce ambiguous code. You
can avoid the worst abuses, but you will encounter several types of barewords
in legacy code.
-=head3 Bareword function calls
-
-X<barewords; function calls>
-X<C<B::Deparse>>
-
-Code written without C<strict 'subs'> may use bareword function names. Adding
-parentheses will make the code pass strictures. Use C<perl -MO=Deparse,-p> (see
-C<perldoc B::Deparse>) to discover how Perl parses them, then parenthesize
-accordingly.
-
=head3 Bareword hash values
X<barewords; hash values>
@@ -171,6 +161,16 @@ When neither the C<Floyd()> nor C<Annette()> functions exist, Perl will
interpret these barewords as strings. C<strict 'subs'> will produce an error in
this situation.
+=head3 Bareword function calls
+
+X<barewords; function calls>
+X<C<B::Deparse>>
+
+Code written without C<strict 'subs'> may use bareword function names. Adding
+parentheses will make the code pass strictures. Use C<perl -MO=Deparse,-p> (see
+C<perldoc B::Deparse>) to discover how Perl parses them, then parenthesize
+accordingly.
+
=head3 Bareword filehandles
X<barewords; filehandles>
View
29 sections/blessed_references.pod
@@ -36,11 +36,11 @@ A constructor is a method which creates and blesses a reference. By convention,
constructors have the name C<new()>, but this is not a requirement.
Constructors are also almost always I<class methods>.
-C<bless> takes two arguments, a reference and a class name. It evaluates to the
-reference. The reference may be to an empty hash or array or a scalar
-containing an undefined value. The class does not have to exist yet. You may
-even use C<bless> outside of a constructor or a class (though all but the
-simplest programs should use real constructors). A constructor can be as simple
+C<bless> takes two operands, a reference and a class name, and evaluates to the
+reference. The reference may be any valid reference, empty or not. The class
+does not have to exist yet. You may even use C<bless> outside of a constructor
+or a classN<... but you're violating encapsulation to expose the details of
+object construction outside of a constructor.>. A constructor can be as simple
as:
=begin programlisting
@@ -275,25 +275,30 @@ team to use Moose in full yet, you can work around some of the problems of
blessed references with discipline.
X<C<Class::Accessor>>
+X<CPAN; C<Role::Tiny>>
=over 4
+=item * Do not mix functions and methods in the same class.
+
+=item * Use a single F<.pm> file for each class, unless the class is a small,
+self-contained helper used from a single place.
+
+=item * Follow standards of vanilla Perl OO, such as naming constructors
+C<new()> and using C<$self> as the invocant name in your documentation.
+
=item * Use accessor methods pervasively, even within methods in your class. A
module such as C<Class::Accessor> helps to avoid repetitive boilerplate.
-=item * Avoid C<AUTOLOAD()> where possible. If you I<must> use it, use forward
-declarations of your functions (L<functions>) to help Perl know which
-C<AUTOLOAD()> will provide the method implementation.
+=item * Avoid C<AUTOLOAD()> where possible. If you I<must> use it, use function
+forward declarations (L<functions>) to avoid ambiguity.
=item * Expect that someone, somewhere will eventually need to subclass (or
delegate to or reimplement the interface of) your classes. Make it easier for
them by not assuming details of the internals of your code, by using the
two-argument form of C<bless>, and by breaking your classes into the smallest
responsible units of code.
-=item * Do not mix functions and methods in the same class.
-
-=item * Use a single F<.pm> file for each class, unless the class is a small,
-self-contained helper used from a single place.
+=item * Use helper modules such as C<Role::Tiny> to allow better use and reuse.
=back
View
63 sections/closures.pod
@@ -20,8 +20,6 @@ You've probably already created and used closures without realizing it:
=begin programlisting
- #!/usr/bin/perl
-
use Modern::Perl '2014';
my $filename = shift @ARGV;
@@ -52,9 +50,9 @@ invoked, will return the next item in the iteration:
}
}
- my $cousins = make_iterator(
- qw( Rick Alex Kaycee Eric Corey Mandy Christine Alex2 )
- );
+ my $cousins = make_iterator(qw(
+ Rick Alex Kaycee Eric Corey Mandy Christine Alex
+ ));
say $cousins->() for 1 .. 6;
@@ -71,9 +69,9 @@ for each invocation:
=begin programlisting
- my $aunts = make_iterator(
- qw( Carole Phyllis Wendy Sylvia Monica Lupe )
- );
+ my $aunts = make_iterator(qw(
+ Carole Phyllis Wendy Sylvia Monica Lupe
+ ));
say $cousins->();
say $aunts->();
@@ -150,9 +148,8 @@ cache and lazily create the elements you need:
=end programlisting
Every call to the function returned by C<gen_fib()> takes one argument, the
-I<n>th element of the Fibonacci series. The function generates all preceding
-values in the series as necessary, caches them, and returns the requested
-element--even delaying computation until absolutely necessary.
+I<n>th element of the Fibonacci series. The function generates and caches all
+preceding values in the series as necessary, and returns the requested element.
Here's where closures and first class functions get interesting. This code does
two things; there's a pattern specific to caching intertwined with the numeric
@@ -177,25 +174,11 @@ calculated or cached value) to a function C<gen_caching_closure()>?
};
}
-=end programlisting
-
-=begin tip Fold, Apply, and Filter
-
-The builtins C<map>, C<grep>, and C<sort> are themselves higher-order
-functions.
-
-=end tip
-
-Now C<gen_fib()> can become:
-
-=begin programlisting
-
sub gen_fib
{
my @fibs = (0, 1, 1);
- return gen_caching_closure(
- sub
+ return B<gen_caching_closure>( sub
{
my ($item, $fibs) = @_;
@@ -204,8 +187,7 @@ Now C<gen_fib()> can become:
$fibs->[$calc] = $fibs->[$calc - 2]
+ $fibs->[$calc - 1];
}
- },
- @fibs
+ }B<, @fibs>
);
}
@@ -217,6 +199,13 @@ number in the Fibonacci series. Customizing the behavior of code--in this case,
C<gen_caching_closure()>--by passing in a function allows tremendous
flexibility and can clean up your code.
+=begin tip Fold, Apply, and Filter
+
+The builtins C<map>, C<grep>, and C<sort> are themselves higher-order
+functions.
+
+=end tip
+
=head2 Closures and Partial Application
Z<partial_application>
@@ -245,10 +234,10 @@ arguments that never change.
X<partial application>
-A technique called I<partial application> allows you to bind I<some> of the
-arguments to a function now so that you can provide the others later. Wrap the
-function you intend to call in a closure and pass the bound arguments. Consider
-that small ice cream cart:
+I<Partial application> allows you to bind I<some> of the arguments to a
+function now so that you can provide the others later. Wrap the function you
+intend to call in a closure and pass the bound arguments. For your ice cream
+cart:
=begin programlisting
@@ -264,11 +253,11 @@ that small ice cream cart:
X<CPAN; C<Sub::Install>>
-Now whenever you process an order, instead of calling C<make_sundae()>
-directly, invoke the function reference in C<$make_cart_sundae> and pass only
-the interesting arguments. You'll never forget the invariants or pass them
-incorrectly. You can even use C<Sub::Install> from the CPAN to import
-C<$make_cart_sundae> function into another namespace.
+Now whenever you process an order, invoke the function reference in
+C<$make_cart_sundae> and pass only the interesting arguments. You'll never
+forget the invariants or pass them incorrectly. You can even use
+C<Sub::Install> from the CPAN to import C<$make_cart_sundae> function into
+another namespace.
X<I<Higher Order Perl>>
View
50 sections/code_generation.pod
@@ -125,13 +125,11 @@ Installing into symbol tables is reasonably easy, if ugly:
=begin programlisting
- {
- my ($get, $set) = generate_accessors( 'pie' );
+ my ($get, $set) = generate_accessors( 'pie' );
- no strict 'refs';
- *{ 'get_pie' } = $get;
- *{ 'set_pie' } = $set;
- }
+ no strict 'refs';
+ *{ 'get_pie' } = $get;
+ *{ 'set_pie' } = $set;
=end programlisting
@@ -147,15 +145,6 @@ functions, and methods. Assigning a reference to a symbol table entry installs
or replaces that entry. To promote an anonymous function to a method, store
that function's reference in the symbol table.
-=begin tip Symbol Tables Simplified
-
-X<CPAN; C<Package::Stash>>
-
-Use the CPAN module C<Package::Stash> instead of manipulating symbol tables
-yourself.
-
-=end tip
-
X<C<strict> pragma>
X<pragmas; C<strict>>
@@ -166,26 +155,22 @@ generate in a single line:
=begin programlisting
- {
- no strict 'refs';
+ no strict 'refs';
- *{ $methname } = sub {
- # subtle bug: strict refs disabled here too
- };
- }
+ *{ $methname } = sub {
+ # subtle bug: strict refs disabled here too
+ };
=end programlisting
This example disables strictures for the outer block I<as well as the body of
the function itself>. Only the assignment violates strict reference checking,
-so disable strictures for that operation alone. In other words:
+so disable strictures for that operation alone:
=begin programlisting
{
- my $sub = sub {
- # strict refs still enabled here
- };
+ my $sub = sub { ... };
no strict 'refs';
*{ $methname } = $sub;
@@ -210,6 +195,15 @@ Assigning directly to the glob does not violate strictures, but mentioning each
glob only once I<does> produce a "used only once" warning you can disable with
the C<warnings> pragma.
+=begin tip Symbol Tables Simplified
+
+X<CPAN; C<Package::Stash>>
+
+Use the CPAN module C<Package::Stash> instead of manipulating symbol tables
+yourself.
+
+=end tip
+
=head2 Compile-time Manipulation
X<builtins; C<eval>>
@@ -280,11 +274,8 @@ name with a scope) and lexical I<assignment>. The former happens during
compilation, while the latter occurs at the point of execution. This code has a
subtle bug:
-X<CPAN; C<UNIVERSAL::require>>
-
=begin programlisting
- # adds a require() method to UNIVERSAL
use UNIVERSAL::require;
# buggy; do not use
@@ -300,7 +291,8 @@ X<CPAN; C<UNIVERSAL::require>>
... because the C<BEGIN> block will execute I<before> the assignment of the
string value to C<$wanted_package> occurs. The result will be an exception from
-attempting to invoke the C<require()> method on an undefined value.
+attempting to invoke the C<require()> methodN<C<UNIVERSAL::require> adds a
+C<require()> method to C<UNIVERSAL>.> on an undefined value.
=head2 Class::MOP
View
2 sections/credits.pod
@@ -67,7 +67,7 @@ Andrew Savige,
Lorne Schachter,
Steve Schulze,
Dan Scott,
-Alexander Scott-Johns,
+Alex-ander Scott-Johns,
Phillip Smith,
Christopher E. Stith,
Mark A. Stratman,
View
5 sections/exceptions.pod
@@ -17,7 +17,8 @@ control flow mechanism designed to raise and handle errors.
Z<throwing_exceptions>
Suppose you want to write a log file. If you can't open the file, something has
-gone wrong. Use C<die> to throw an exception:
+gone wrong. Use C<die> to throw an exceptionN<... or let C<autodie>
+(L<autodie>) add it for you, in this case.>:
=begin programlisting
@@ -193,7 +194,7 @@ X<C<Try::Tiny>>
Perl 5.14 fixed some of these issues. They occur rarely, but they're often
difficult to diagnose and to fix. The C<Try::Tiny> CPAN distribution improves
-the safety of exception handling I<and> the syntaxN<C<Try::Tiny> helped inspire
+the safety of exception handling I<and> the syntaxN<C<Try::Tiny> inspired
improvements to Perl 5.14's exception handling.>.
C<Try::Tiny> is easy to use:
View
16 sections/files.pod
@@ -108,21 +108,21 @@ You can even create filehandles which read from or write to plain Perl scalars,
=end programlisting
-=begin tip Remember C<autodie>?
-
-All examples in this section have C<use autodie;> enabled, and so can safely
-elide error handling. If you choose not to use C<autodie>, remember to check
-the return values of all system calls to handle errors appropriately.
-
-=end tip
-
X<builtins; C<sysopen>>
C<perldoc perlopentut> explains in detail more exotic uses of C<open>,
including its ability to launch and control other processes, as well as the use
of C<sysopen> for finer-grained control over input and output. C<perldoc
perlfaq5> includes working code for many common IO tasks.
+=begin tip Remember C<autodie>?
+
+Assume all of the examples in this section have C<use autodie;> enabled, and so
+can safely elide error handling. If you choose not to use C<autodie>, remember
+to check the return values of all system calls to handle errors appropriately.
+
+=end tip
+
=head3 Unicode, IO Layers, and File Modes
X<IO layers>
View
78 sections/functions.pod
@@ -46,8 +46,8 @@ While these parentheses are not strictly necessary for these examples--even
with C<strict> enabled--they provide clarity to human readers as well as Perl's
parser. When in doubt, leave them in.
-Function arguments can be arbitrary expressions, including variables and
-expressions:
+Function arguments can be arbitrary expressions--including variables and
+function calls:
=begin programlisting
@@ -117,14 +117,9 @@ use list assignment, but some code will access individual elements by index:
=end programlisting
-You may also C<unshift>, C<push>, C<pop>, C<splice>, and slice C<@_>.
-
-=begin tip The Implicit Them
-
-Remember that the array builtins use C<@_> as the default operand I<within
-functions>, so that C<my $name = shift;> works. Take advantage of this idiom.
-
-=end tip
+You may also C<unshift>, C<push>, C<pop>, C<splice>, and slice C<@_>. Remember
+that the array builtins use C<@_> as the default operand I<within functions>,
+so that C<my $name = shift;> works. Take advantage of this idiom.
Assigning a scalar parameter from C<@_> requires C<shift>, indexed access to
C<@_>, or lvalue list context parentheses. Otherwise, Perl will happily
@@ -146,29 +141,23 @@ C<shift>. Compare:
=begin programlisting
- sub calculate_value_shifty
- {
- # multiple shifts
- my $left_value = shift;
- my $operation = shift;
- my $right_value = shift;
- ...
- }
+ my $left_value = shift;
+ my $operation = shift;
+ my $right_value = shift;
=end programlisting
... to:
=begin programlisting
- sub calculate_value_assigny
- {
- B<my ($left_value, $operation, $right_value) = @_;>
- ...
- }
+ my ($left_value, $operation, $right_value) = @_;
=end programlisting
+The latter is simpler to read and is even slightly more efficient (though its
+improved readability is much more important).
+
Occasionally it's necessary to extract parameters from C<@_> and pass the rest
to another function:
@@ -194,12 +183,14 @@ X<CPAN; C<Function::Parameters>>
X<CPAN; C<Method::Signatures>>
X<CPAN; C<MooseX::Method::Signatures>>
X<CPAN; C<Method::Signatures::Simple>>
+X<CPAN; C<Moops>>
Several CPAN distributions extend Perl's parameter handling with additional
syntax and options. C<signatures> and C<Method::Signatures> are powerful.
C<Method::Signatures::Simple> is basic, but useful.
C<MooseX::Method::Signatures> works very well with Moose (L<moose>).
-C<Function::Parameters> is worth exploring.
+C<Function::Parameters> is worth exploring. C<Moops> goes much further to add
+OO syntax, but bundles good function signatures as well.
=end tip
@@ -331,18 +322,14 @@ function within another namespace by prefixing its name:
=begin programlisting
- sub B<Extensions::Math::>add {
- ...
- }
+ sub B<Extensions::Math::>add { ... }
=end programlisting
This will declare the function and create the namespace as necessary. Remember
-that Perl packages are open for modification at any pointN<Yes, even while your
-program is running.>. You may only declare one function of the same name per
-namespace. Otherwise Perl will warn you about subroutine redefinition. Disable
-this warning with C<no warnings 'redefine'> if you're certain this is what you
-intend.
+that Perl packages are open for modification at any point--even while your
+program is running. If you declare multiple functions with the same name in a
+single namespace, Perl will issue a warning.
You can refer to other functions within a namespace with their short names. Use
a fully-qualified name to invoke a function in another namespace:
@@ -503,12 +490,15 @@ correct:
=end programlisting
+This validation reports any parameter count error from the point of view of its
+caller, thanks to the use of C<croak>.
+
X<CPAN; C<Params::Validate>>
X<CPAN; C<MooseX::Method::Signatures>>
Type checking is more difficult, because of Perl's operator-oriented type
-conversions (L<context_philosophy>). The CPAN module C<Params::Validate> offers
-more strictness, as do some of the function signature modules such as
+conversions (L<context_philosophy>). If you want additional safety of function
+parameters, see CPAN modules such as C<Params::Validate> or
C<MooseX::Method::Signatures>.
=head1 Advanced Functions
@@ -617,8 +607,7 @@ values of the lexical variables is separate from the function itself, you can
have multiple calls to a function active at the same time. A function can even
call itself, or I<recur>.
-To make the previous test pass, write a function named C<elem_exists()> which
-knows how to halve the list and call itself:
+To make the previous test pass, write the recursive function C<elem_exists()>:
=begin programlisting
@@ -652,10 +641,10 @@ knows how to halve the list and call itself:
=end programlisting
-If you've never seen this before, it may take some time to understand. Keep in
-mind that the arguments to the function will be different every time it gets
-called (otherwise it would never terminate; it would continue recursing until
-it crashes). That's why the termination condition is so important.
+Keep in mind that the arguments to the function will be I<different> for every
+call, otherwise the function would always behave the same way (it would
+continue recursing until the program crashes).That's why the termination
+condition is so important.
Every recursive program can be written without recursionN<See the free book
I<Higher Order Perl> at U<http://hop.perl.plover.com/>.>, but this
@@ -683,8 +672,6 @@ invocation are safe and separate:
my ($item, @array) = @_;
B<cluck "[$item] (@array)";>
-
- # other code follows
...
}
@@ -698,11 +685,9 @@ X<recursion; guard conditions>
One I<drawback> of recursion is that you must get your return conditions
correct, lest your function call itself an infinite number of times.
C<elem_exists()> function has several C<return> statements for this reason.
-
Perl offers a helpful C<Deep recursion on subroutine> warning when it suspects
runaway recursion. The limit of 100 recursive calls is arbitrary, but often
-useful. Disable this warning with C<no warnings 'recursion'> in the scope of
-the recursive call.
+useful. Disable this warning with C<no warnings 'recursion'>.
Because each call to a function requires a new call frame and lexical storage
space, highly-recursive code can use more memory than iterative code. I<Tail
@@ -813,5 +798,4 @@ non-number (the test description, which it cannot convert into a number) with
the element in the array.
While extraneous parentheses can hamper readability, thoughtful use of
-parentheses can clarify code and make subtle bugs unlikely. As you improve your
-understanding of Perl, look for ways to write clear and unambiguous code.
+parentheses can clarify code and make subtle bugs unlikely.
View
4 sections/handling_warnings.pod
@@ -166,8 +166,8 @@ X<warnings; catching>
If you're willing to work for it, you can catch warnings as you would
exceptions. The C<%SIG> variableN<See C<perldoc perlvar>.> contains handlers
-for out-of-band signals raised by Perl or your operating system. To catch a
-warning, assign a function reference to C<$SIG{__WARN__}>:
+for out-of-band signals raised by Perl or your operating system. Assign a
+function reference to C<$SIG{__WARN__}> to catch a warning:
=begin programlisting
View
13 sections/idioms.pod
@@ -369,7 +369,7 @@ Suppose your function takes exactly two arguments. You I<could> write:
{
if (@_ != 2)
{
- croak 'Grooming requires two monkeys!';
+ croak 'Can only groom two monkeys!';
}
...
}
@@ -381,16 +381,7 @@ the check and deserve to be at the I<start> of the expression:
=begin programlisting
- croak 'Grooming requires two monkeys!' if @_ != 2;
-
-=end programlisting
-
-... which may read more simply as:
-
-=begin programlisting
-
- croak 'Grooming requires two monkeys!'
- unless @_ == 2;
+ croak 'Can only groom two monkeys!' unless @_ == 2;
=end programlisting
View
6 sections/indirect_objects.pod
@@ -33,7 +33,7 @@ example, the verb (the method) precedes the noun to which it refers (the
object). This is fine in spoken languages, but it introduces parsing
ambiguities in Perl.
-Because the method's name is a bareword (L<barewords>), the parser use several
+Because the method's name is a bareword (L<barewords>), the parser uses several
heuristics to figure out the proper interpretation of this code. While these
heuristics are well-tested and I<almost> always correct, their failure modes
are confusing. Things get worse when you pass arguments to a constructor:
@@ -49,7 +49,9 @@ In this example, the I<name> of the class looks like a function call. Perl
I<can> disambiguate many of these cases, but its heuristics depend on which
package names the parser has seen, which barewords it has already resolved (and
how it resolved them), and the I<names> of functions already declared in the
-current package.
+current package. For an exhaustive list of these conditions, you have to read
+the source code of Perl's parser--not something the average Perl programmer
+wants to do.
Imagine running afoul of a prototyped function (L<prototypes>) with a name
which just happens to conflict somehow with the name of a class or a method
View
76 sections/moose.pod
@@ -9,11 +9,24 @@ little clunky, and it exposes I<how> an object system works. You can build
great things on top of it, but you or someone else will have to build a lot of
code to get what some other languages provide for free.
-I<Moose> is a complete object system for PerlN<See C<perldoc Moose::Manual>.>
-Moose offers both a simpler way to use an object system as well as advanced
-features of languages such as Smalltalk and Common Lisp. Moose objects work
-with plain vanilla Perl. Moose is a great way to write object oriented code in
-Perl.
+I<Moose> is a complete object system for Perl. It's a complete distribution
+available from the CPAN--not a part of the core language, but worth installing
+and using regardless. Moose offers both a simpler way to use an object system
+as well as advanced features of languages such as Smalltalk and Common Lisp.
+
+Moose objects work with plain vanilla Perl. Within your programs, you can mix
+and match objects written with Perl's default object system and Moose. Of
+course, you have to write a lot more code to get what Moose provides for you.
+
+X<CPAN; C<Moose>>
+X<CPAN; C<Moose::Manual>>
+
+=begin tip Moose Documentation
+
+See C<Moose::Manual> on the CPAN for comprehensive Moose documentation.
+
+=end tip
+
=head2 Classes
@@ -45,8 +58,7 @@ a class. Create objects (or I<instances>) of the C<Cat> class with the syntax:
=end programlisting
-Just as an arrow dereferences a reference, an arrow calls a method on an object
-or class.
+Just as an arrow dereferences a reference, this arrow calls a method on C<Cat>.
=head2 Methods
@@ -71,18 +83,8 @@ When you call a method on an object, that object is the invocant:
=end programlisting
-X<dispatch>
-X<method dispatch>
-X<OO; dispatch>
-X<OO; method dispatch>
-
-A method call always involves a I<dispatch> strategy. This strategy controls
-how Perl selects the appropriate method. This may seem obvious, given how
-simple the C<Cat> class is, but much of the power of OO comes from method
-dispatch.
-
-When invoked, a method's first argument is its invocant. Idiomatic Perl uses
-C<$self> as its name. Suppose a C<Cat> can C<meow()>:
+A method's first argument is its invocant (C<$self>, by convention). Suppose a
+C<Cat> can C<meow()>:
=begin programlisting
@@ -158,15 +160,13 @@ class:
=end programlisting
-In English, that reads "C<Cat> objects have a C<name> attribute. It's
-read-only, and is a string."
-
-Using Moose makes the C<has()> function available. C<has()> declares an
-attribute. The first argument, C<'name'> here, is the attribute's name. The C<<
-is => 'ro' >> pair of arguments declares that this attribute is C<r>ead
-C<o>nly, so you cannot modify the attribute's value after you've set it.
-Finally, the C<< isa => 'Str' >> pair declares that the value of this attribute
-can only be a C<str>ing.
+Moose exports the C<has()> function for you to use to declare an attribute. In
+English, this code reads "C<Cat> objects have a C<name> attribute. It's
+read-only, and is a string." The first argument, C<'name'>, is the attribute's
+name. The C<< is => 'ro' >> pair of arguments declares that this attribute is
+C<r>ead C<o>nly, so you cannot modify the attribute's value after you've set
+it. Finally, the C<< isa => 'Str' >> pair declares that the value of this
+attribute can only be a C<str>ing.
X<methods; accessor>
X<OO; accessor methods>
@@ -744,6 +744,16 @@ X<objects; inheritance>
X<objects; multiple inheritance>
X<MRO>
+X<dispatch>
+X<method dispatch>
+X<OO; dispatch>
+X<OO; method dispatch>
+
+A method call always involves a I<dispatch> strategy. This strategy controls
+how Perl selects the appropriate method. This may seem obvious, given how
+simple the C<Cat> class is, but much of the power of OO comes from method
+dispatch.
+
I<Method dispatch order> (or I<method resolution order> or I<MRO>) is obvious
for single-parent classes. Look in the object's class, then its parent, and so
on until you find the method or run out of parents. Classes which inherit from
@@ -824,14 +834,8 @@ overridden method:
This subclass adds a warning when trying to light or extinguish a light source
that already has the current state. The C<super()> function dispatches to the
nearest parent's implementation of the current method, per the normal Perl
-method resolution order.
-
-=begin tip Powered by Moose
-
-Moose's method modifiers can do similar things--and more. See C<perldoc
-Moose::Manual::MethodModifiers>.
-
-=end tip
+method resolution order. (See C<perldoc Moose::Manual::MethodModifiers> for
+more dispatch options.)
=head3 Inheritance and isa()
View
6 sections/operator_types.pod
@@ -245,8 +245,7 @@ evaluated in list context with a scalar as its first operand, it produces a
string consisting of the string value of its first operand concatenated to
itself the number of times specified by its second operand.
-In scalar context, the operator always produces a concatenated string repeated
-appropriately. For example:
+In scalar context, the operator repeats and concatenates a string:
=begin programlisting
@@ -280,8 +279,7 @@ The infix I<range> operator (C<..>) produces a list of items in list context:
=end programlisting
-It can produce simple, incrementing ranges (both as integers or strings), but
-it cannot intuit patterns or more complex ranges.
+It can I<only> produce simple, incrementing ranges of integers or strings.
X<operators; flip-flop>
X<flip-flop>
View
5 sections/pragmas.pod
@@ -27,7 +27,6 @@ effective within a scope as well:
use strict;
my $lexical = 'available here';
# $lexical B<is> visible; strict B<is> in effect
- ...
}
# $lexical again invisible; strict B<not> in effect
}
@@ -45,7 +44,6 @@ effects within inner scopes:
{
# inner scope, but strict still in effect
my $inner = 'another lexical';
- ...
}
=end programlisting
@@ -78,8 +76,7 @@ protection of C<strict> when you need to do something symbolic:
=begin programlisting
- use Modern::Perl;
- # or use strict;
+ use Modern::Perl; # or use strict;
{
no strict 'refs';
View
17 sections/prototypes.pod
@@ -4,7 +4,7 @@ Z<prototypes>
X<prototypes>
-A I<prototype> is a piece metadata attached to a function or variable. A
+A I<prototype> is a piece of metadata attached to a function or variable. A
function prototype changes how Perl's parser understands it.
X<builtins; C<push>>
@@ -35,8 +35,9 @@ include it for the full declaration--but there's no reason to do so.
X<builtins; C<prototype>>
The builtin C<prototype> takes the name of a function and returns a string
-representing its prototype. Use the C<CORE::> form to see the prototype of a
-builtin:
+representing its prototype.
+
+To see the prototype of a builtin, use the C<CORE::> form of the builtin's name as the operand to C<prototype>:
=begin screen
@@ -129,8 +130,14 @@ incoming arguments:
=end programlisting
To debug this, users of C<mypush> must know both that a prototype exists, and
-the limitations of the array prototype. Worse yet, these are the I<simple>
-errors prototypes can cause.
+the limitations of the array prototype.
+
+=begin tip Debugging Prototype Errors
+
+If you think this error message is inscrutable, wait until you see the
+I<complicated> prototype errors.
+
+=end tip
=head2 Good Uses of Prototypes
View
50 sections/regular_expressions.pod
@@ -312,15 +312,14 @@ C<Alabama>, C<Belgium>, and C<Bethlehem> long before it reaches the answer of
C<loam>. Not only are those words too long, but the matches start in the middle
of the words.
-It's important to know how the regex engine handles greedy matches--but it's
-equally as important to know what kind of matches you do and don't want.
-
=head1 Regex Anchors
X<regex; anchors>
X<anchors; start of string>
X<C<\A>; start of string regex metacharacter>
+It's important to know how the regex engine handles greedy matches--but it's
+equally as important to know what kind of matches you do and don't want.
I<Regex anchors> force the regex engine to start or end a match at a fixed
position. The I<start of string anchor> (C<\A>) dictates that any match must
start at the very beginning of the string:
@@ -351,11 +350,11 @@ X<C<^>; start of string after newline regex metacharacter>
X<C<$>; end of string before newline regex metacharacter>
You will often see the C<^> and C<$> assertions used to match the start and end
-of strings, but that's not exactly what they do. C<^> does match the start of
-the string, but in certain circumstances it can match just after a newline
-within the string. Similarly, C<$> does match the end of the string (just
-before a newline, if it exists), but it can match just before a newline in the
-middle of the string. Usually you want C<\A> and C<\z> instead.
+of strings. C<^> I<does> match the start of the string, but in certain
+circumstances it can match just after a newline within the string. Similarly,
+C<$> I<does> match the end of the string (just before a newline, if it exists),
+but it can match just before a newline in the middle of the string. C<\A> and
+C<\z> are more specific and, thus, more useful.
X<word boundary metacharacter>
X<C<\b>; word boundary regex metacharacter>
@@ -526,14 +525,10 @@ Use the caret (C<^>) as the first element of the character class to mean
=end programlisting
-=begin tip Metacharacters in Character Classes
-
Use a caret anywhere but the first position to make it a member of the
character class. To include a hyphen in a negated character class, place it
after the caret or at the end of the class, or escape it.
-=end tip
-
=head1 Capturing
Z<regex_captures>
@@ -699,7 +694,7 @@ X<regex; alternation>
X<C<|>; alternation regex metacharacter>
Some regexes need to match either one thing or another. The I<alternation>
-metacharacter (C<|>) expresses this intent:
+metacharacter (C<|>) indicates that either possibility may match.
=begin programlisting
@@ -711,9 +706,13 @@ metacharacter (C<|>) expresses this intent:
=end programlisting
-The alternation metacharacter indicates that either preceding fragment may
-match. Keep in mind that alternation has a lower precedence (L<precedence>)
-than even atoms:
+While it's easy to interpret C<rice|beans> as meaning C<ric>, followed by
+either C<e> or C<b>, followed by C<eans>, alternations always include the
+I<entire> fragment to the nearest regex delimiter, whether the start or end of
+the pattern, an enclosing parenthesis, another alternation character, or a
+square bracket.
+
+Alternation has a lower precedence (L<precedence>) than even atoms:
=begin programlisting
@@ -723,12 +722,6 @@ than even atoms:
=end programlisting
-While it's easy to interpret C<rice|beans> as meaning C<ric>, followed by
-either C<e> or C<b>, followed by C<eans>, alternations always include the
-I<entire> fragment to the nearest regex delimiter, whether the start or end of
-the pattern, an enclosing parenthesis, another alternation character, or a
-square bracket.
-
X<regex; C<()>>
X<C<()>; capturing regex metacharacters>
@@ -791,9 +784,9 @@ characters instead of treating the asterisks as greedy quantifiers.
=begin tip Regex Security
Be cautious when processing regular expressions from untrusted user input. A
-malicious regex master can craft a denial-of-service attack against your
-program. Because the regex engine may backtrack to make greedy matches work,
-you can write regexes that will take years to match input strings.
+malicious regex master can craft a regular expression which may take I<years>
+to match input strings, creating a denial-of-service attack against your
+program.
=end tip
@@ -830,13 +823,12 @@ I<zero-width negative look-ahead assertion>:
=end programlisting
-The construct C<(?!...)> matches the phrase C<cat> only if the phrase
-C<astrophe> does not immediately follow.
-
X<regex; zero-width positive look-ahead assertion>
X<C<(?=...)>; zero-width positive look-ahead regex assertion>
-The I<zero-width positive look-ahead assertion>:
+The construct C<(?!...)> matches the phrase C<cat> only if the phrase
+C<astrophe> does not immediately follow. The I<zero-width positive look-ahead
+assertion>:
=begin programlisting
View
10 sections/scope.pod
@@ -70,7 +70,9 @@ X<lexical shadowing>
X<scope; lexical shadowing>
Declaring a lexical in an inner scope with the same name as a lexical in an
-outer scope hides, or I<shadows>, the outer lexical within the inner scope:
+outer scope hides, or I<shadows>, the outer lexical within the inner scope.
+
+For example:
=begin programlisting
@@ -85,9 +87,9 @@ outer scope hides, or I<shadows>, the outer lexical within the inner scope:
=end programlisting
-This toy example is obviously silly, but in longer code with larger scopes,
-this shadowing behavior is often desirable--it's easier to understand code when
-the scope of a lexical variable is no more than a couple of dozen lines.
+In longer code with larger scopes, this shadowing behavior is often
+desirable--it's easier to understand code when the scope of a lexical variable
+is no more than a couple of dozen lines.
=begin tip Name Collisions
View
1 sections/smart_match.pod
@@ -50,7 +50,6 @@ These examples are deliberately simple, because smart match can be confusing:
my $z = '10 little endians';
say 'Equal numeric-ishally' if $x ~~ $z;
- # regular expression match
my $needle = qr/needle/;
say 'Pattern match' if 'needle' ~~ $needle;
View
26 sections/state.pod
@@ -2,9 +2,8 @@
Z<state>
-Closures (L<closures>) take advantage of lexical scope (L<scope>) to control
-access to lexical variables. Outside of a closure, you can't manipulate the
-lexical. Inside the closure, you can. Even named functions can do this:
+Closures (L<closures>) use lexical scope (L<scope>) to control access to
+lexical variables--even with named functions:
=begin programlisting
@@ -23,13 +22,10 @@ lexical. Inside the closure, you can. Even named functions can do this:
=end programlisting
-The encapsulation of functions to toggle the safety allows all three functions
-to share state without exposing the lexical variable directly to external code.
-This idiom works well for cases where external code should be able to change
-internal state, but it's clunkier when only one function needs to manage that
-state.
-
-Suppose every hundredth person at your ice cream parlor gets free sprinkles:
+All three functions encapsulate that shared state without exposing the lexical
+variable directly to external code. This idiom works well for cases where
+multiple functions access that lexical, but it's clunky when only one function
+does. Suppose every hundredth ice cream parlor customer gets free sprinkles:
=begin programlisting
@@ -38,11 +34,9 @@ Suppose every hundredth person at your ice cream parlor gets free sprinkles:
sub serve_customer
{
$cust_count++;
-
my $order = shift;
add_sprinkles($order) if $cust_count % 100 == 0;
-
...
}
@@ -51,9 +45,9 @@ Suppose every hundredth person at your ice cream parlor gets free sprinkles:
X<state>
X<builtins; C<state>>
-This approach I<works>, but creating a new lexical scope for a single function
-is a little bit noisy. The C<state> builtin allows you to declare a lexically
-scoped variable with a value that persists between invocations:
+This approach I<works>, but creating a new outer lexical scope for a single
+function is a little bit noisy. The C<state> builtin allows you to declare a
+lexically scoped variable with a value that persists between invocations:
=begin programlisting
@@ -113,7 +107,7 @@ you encounter it:
sub inadvertent_state
{
# my $counter = 1 if 0; # DEPRECATED; don't use
- state $counter = 1; # use instead
+ state $counter = 1; # prefer
...
}
View
8 sections/taint.pod
@@ -10,7 +10,7 @@ understanding and can help you avoid subtle mistakes.
X<taint>
-I<Taint mode> (or I<taint>) is a sticky piece metadata attached to all data
+I<Taint mode> (or I<taint>) is a sticky piece of metadata attached to all data
which comes from outside of your program. Any data derived from tainted data is
also tainted. You may use tainted data within your program, but if you use it
to affect the outside world--if you use it insecurely--Perl will throw a fatal
@@ -57,8 +57,10 @@ X<taint; untainting>
X<untainting>
To remove taint, you must extract known-good portions of the data with a
-regular expression capture. That captured data will be untainted. If your user
-input consists of a US telephone number, you can untaint it with:
+regular expression capture. That captured data will be untainted.
+
+For example, if your user input consists of a US telephone number, you can
+untaint it with:
=begin programlisting
View
6 sections/tie.pod
@@ -57,8 +57,8 @@ X<builtins; C<tied>>
Tying functions resemble constructors: C<TIESCALAR>, C<TIEARRAY()>,
C<TIEHASH()>, or C<TIEHANDLE()> for scalars, arrays, hashes, and filehandles
respectively. Each function returns a new object which represents the tied
-variable. Both the C<tie> and C<tied> builtins return this object. Most people
-use C<tied> in a boolean context, however.
+variable. Both C<tie> and C<tied> return this object, though most people use
+C<tied> in a boolean context.
=head2 Implementing Tied Variables
@@ -94,8 +94,6 @@ Here's a class which logs all reads from and writes to a scalar:
}
}
- 1;
-
=end programlisting
Assume that the C<Logger> class method C<log()> takes a string and the number
View
161 sections/universal.pod
@@ -6,48 +6,58 @@ X<C<UNIVERSAL>>
Perl's builtin C<UNIVERSAL> package is the ancestor of all other packages--in
the object-oriented sense (L<moose>). C<UNIVERSAL> provides a few methods for
-its children to inherit or override.
+its children to use, inherit, or override.
-=head2 The isa() Method
+=head2 The VERSION() Method
-X<C<UNIVERSAL::isa>>
-X<C<isa()>>
-X<C<SCALAR>>
-X<C<ARRAY>>
-X<C<HASH>>
-X<C<Regexp>>
-X<C<IO>>
-X<C<CODE>>
+X<C<UNIVERSAL::VERSION>>
+X<C<VERSION()>>
-The C<isa()> method takes a string containing the name of a class or the name
-of a core type (C<SCALAR>, C<ARRAY>, C<HASH>, C<Regexp>, C<IO>, and C<CODE>).
-Call it as a class method or an instance method on an object. C<isa()> returns
-a true value if its invocant is or derives from the named class, or if the
-invocant is a blessed reference to the given type.
+The C<VERSION()> method returns the value of the C<$VERSION> variable of the
+invoking package or class. If you provide a version number as an optional
+parameter, the method will throw an exception if the queried C<$VERSION> is not
+equal to or greater than the parameter.
-Given an object C<$pepper> (a hash reference blessed into the C<Monkey> class,
-which inherits from the C<Mammal> class):
+Given a C<HowlerMonkey> module of version C<1.23>:
=begin programlisting
- say $pepper->isa( 'Monkey' ); # prints 1
- say $pepper->isa( 'Mammal' ); # prints 1
- say $pepper->isa( 'HASH' ); # prints 1
- say Monkey->isa( 'Mammal' ); # prints 1
+ my $hm = HowlerMonkey->new;
- say $pepper->isa( 'Dolphin' ); # prints 0
- say $pepper->isa( 'ARRAY' ); # prints 0
- say Monkey->isa( 'HASH' ); # prints 0
+ say HowlerMonkey->VERSION; # prints 1.23
+ say $hm->VERSION; # prints 1.23
+ say $hm->VERSION( 0.0 ); # prints 1.23
+ say $hm->VERSION( 1.23 ); # prints 1.23
+ say $hm->VERSION( 2.0 ); # exception!
=end programlisting
-X<CPAN; C<Test::MockObject>>
-X<CPAN; C<Test::MockModule>>
+There's little reason to override C<VERSION()>.
-Any class may override C<isa()>. This can be useful when working with mock
-objects (see C<Test::MockObject> and C<Test::MockModule> on the CPAN) or with
-code that does not use roles (L<roles>). Be aware that any class which I<does>
-override C<isa()> generally has a good reason for doing so.
+=head2 The DOES() Method
+
+X<C<UNIVERSAL::DOES>>
+X<C<DOES()>>
+
+The C<DOES()> method supports the use of roles (L<roles>) in programs. Pass it
+an invocant and the name of a role, and the method will return true if the
+appropriate class somehow does that role--whether through inheritance,
+delegation, composition, role application, or any other mechanism.
+
+The default implementation of C<DOES()> falls back to C<isa()>, because
+inheritance is one mechanism by which a class may do a role. Given a
+C<Cappuchin>:
+
+=begin programlisting
+
+ say Cappuchin->DOES( 'Monkey' ); # prints 1
+ say $cappy->DOES( 'Monkey' ); # prints 1
+ say Cappuchin->DOES( 'Invertebrate' ); # prints 0
+
+=end programlisting
+
+Override C<DOES()> if you manually consume a role or otherwise somehow provide
+allomorphic equivalence.
=head2 The can() Method
@@ -61,24 +71,20 @@ or the name of a package. In the latter case, it returns a reference to a
function, not a methodN<... not that you can tell the difference, given only a
reference.>.
-=begin tip Does a Class Exist?
-
-While both C<UNIVERSAL::isa()> and C<UNIVERSAL::can()> are methods
-(L<method_sub_equivalence>), you may I<safely> use the latter as a function
-solely to determine whether a class exists in Perl. If C<UNIVERSAL::can(
-$classname, 'can' )> returns a true value, someone somewhere has defined a
-class of the name C<$classname>. That class may not be usable, but it does
-exist.
-
-=end tip
-
Given a class named C<SpiderMonkey> with a method named C<screech>, get a
reference to the method with:
=begin programlisting
if (my $meth = SpiderMonkey->can( 'screech' )) {...}
+=end programlisting
+
+This technique leads to the pattern of checking for a method's existence before
+dispatching to it:
+
+=begin programlisting
+
if (my $meth = $sm->can( 'screech' )
{
# method; not a function
@@ -118,54 +124,57 @@ managing plugin systems. Get to know both distributions.
=end tip
-=head2 The VERSION() Method
+=head2 The isa() Method
-X<C<UNIVERSAL::VERSION>>
-X<C<VERSION()>>
+X<C<UNIVERSAL::isa>>
+X<C<isa()>>
+X<C<SCALAR>>
+X<C<ARRAY>>
+X<C<HASH>>
+X<C<Regexp>>
+X<C<IO>>
+X<C<CODE>>
-The C<VERSION()> method returns the value of the C<$VERSION> variable of the
-invoking package or class. If you provide a version number as an optional
-parameter, the method will throw an exception if the queried C<$VERSION> is not
-equal to or greater than the parameter.
+The C<isa()> method takes a string containing the name of a class or the name
+of a core type (C<SCALAR>, C<ARRAY>, C<HASH>, C<Regexp>, C<IO>, and C<CODE>).
+Call it as a class method or an instance method on an object. C<isa()> returns
+a true value if its invocant is or derives from the named class, or if the
+invocant is a blessed reference to the given type.
-Given a C<HowlerMonkey> module of version C<1.23>:
+Given an object C<$pepper> (a hash reference blessed into the C<Monkey> class,
+which inherits from the C<Mammal> class):
=begin programlisting
- say HowlerMonkey->VERSION; # prints 1.23
- say $hm->VERSION; # prints 1.23
- say $hm->VERSION( 0.0 ); # prints 1.23
- say $hm->VERSION( 1.23 ); # prints 1.23
- say $hm->VERSION( 2.0 ); # exception!
-
-=end programlisting
-
-There's little reason to override C<VERSION()>.
-
-=head2 The DOES() Method
+ say $pepper->isa( 'Monkey' ); # prints 1
+ say $pepper->isa( 'Mammal' ); # prints 1
+ say $pepper->isa( 'HASH' ); # prints 1
+ say Monkey->isa( 'Mammal' ); # prints 1
-X<C<UNIVERSAL::DOES>>
-X<C<DOES()>>
+ say $pepper->isa( 'Dolphin' ); # prints 0
+ say $pepper->isa( 'ARRAY' ); # prints 0
+ say Monkey->isa( 'HASH' ); # prints 0
-The C<DOES()> method supports the use of roles (L<roles>) in programs. Pass it
-an invocant and the name of a role, and the method will return true if the
-appropriate class somehow does that role--whether through inheritance,
-delegation, composition, role application, or any other mechanism.
+=end programlisting
-The default implementation of C<DOES()> falls back to C<isa()>, because
-inheritance is one mechanism by which a class may do a role. Given a
-C<Cappuchin>:
+X<CPAN; C<Test::MockObject>>
+X<CPAN; C<Test::MockModule>>
-=begin programlisting
+Any class may override C<isa()>. This can be useful when working with mock
+objects (see C<Test::MockObject> and C<Test::MockModule> on the CPAN) or with
+code that does not use roles (L<roles>). Be aware that any class which I<does>
+override C<isa()> generally has a good reason for doing so.
- say Cappuchin->DOES( 'Monkey' ); # prints 1
- say $cappy->DOES( 'Monkey' ); # prints 1
- say Cappuchin->DOES( 'Invertebrate' ); # prints 0
+=begin tip Does a Class Exist?
-=end programlisting
+While both C<UNIVERSAL::isa()> and C<UNIVERSAL::can()> are methods
+(L<method_sub_equivalence>), you may I<safely> use the latter as a function
+solely to determine whether a class exists in Perl. If C<UNIVERSAL::can(
+$classname, 'can' )> returns a true value, someone somewhere has defined a
+class of the name C<$classname>. That class may not be usable, but it does
+exist.
-Override C<DOES()> if you manually provide a role or provide other allomorphic
-behavior.
+=end tip
=head2 Extending UNIVERSAL

0 comments on commit 4d33f05

Please sign in to comment.
Something went wrong with that request. Please try again.