=head1 NAME
-perltoot - tchrist's object-oriented perl tutorial (rev 0.4)
+perltoot - Tom's object-oriented tutorial for perl
=head1 DESCRIPTION
Asking an object to do something for you is calling an I<object method>.
Asking either a class (usually) or an object (sometimes) to give you
back an object is calling a I<constructor>, which is just a
-particular kind of method.
+kind of method.
That's all well and good, but how is an object different from any other
Perl data type? Just what is an object I<really>; that is, what's its
While a constructor may be named anything you'd like, most Perl
programmers seem to like to call theirs new(). However, new() is not
a reserved word, and a class is under no obligation to supply such.
-Some programmers have also been known to use a function with
+Some programmers have also been known to use a function with
the same name as the class as the constructor.
=head2 Object Representation
By far the most common mechanism used in Perl to represent a Pascal
-record, a C struct, or a C++ class an anonymous hash. That's because a
+record, a C struct, or a C++ class is an anonymous hash. That's because a
hash has an arbitrary number of data fields, each conveniently accessed by
-an arbitrary name of your own devising.
+an arbitrary name of your own devising.
If you were just doing a simple
struct-like emulation, you would likely go about it something like this:
PEERS => [ "Norbert", "Rhys", "Phineas"],
};
-And so you could get at C<$rec-E<gt>{NAME}> to find "Jason", or
-C<@{ $rec-E<gt>{PEERS} }> to get at "Norbert", "Rhys", and "Phineas".
+And so you could get at C<< $rec->{NAME} >> to find "Jason", or
+C<< @{ $rec->{PEERS} } >> to get at "Norbert", "Rhys", and "Phineas".
(Have you ever noticed how many 23-year-old programmers seem to
be named "Jason" these days? :-)
class. If you try to call an undefined method on an object, Perl won't
complain, but the program will trigger an exception while it's running.
Likewise, if you call a method expecting a prime number as its argument
-with an even one instead, you can't expect the compiler to catch this.
+with a non-prime one instead, you can't expect the compiler to catch this.
(Well, you can expect it all you like, but it's not going to happen.)
-Let's suppose you have a well-educated user of you Person class,
+Let's suppose you have a well-educated user of your Person class,
someone who has read the docs that explain the prescribed
interface. Here's how they might use the Person class:
Destruction happens automatically via Perl's garbage collection (GC)
system, which is a quick but somewhat lazy reference-based GC system.
To know what to call, Perl insists that the destructor be named DESTROY.
+Perl's notion of the right time to call a destructor is not well-defined
+currently, which is why your destructors should not rely on when they are
+called.
-Why is DESTROY in all caps? Perl on occasion uses purely upper-case
+Why is DESTROY in all caps? Perl on occasion uses purely uppercase
function names as a convention to indicate that the function will
be automatically called by Perl in some way. Others that are called
implicitly include BEGIN, END, AUTOLOAD, plus all methods used by
the best we can do right now. Nonetheless, rest assured that when your
program is finished, its objects' destructors are all duly called.
So you are guaranteed that an object I<eventually> gets properly
-destructed, except in the unique case of a program that never exits.
+destroyed, except in the unique case of a program that never exits.
(If you're running Perl embedded in another application, this full GC
pass happens a bit more frequently--whenever a thread shuts down.)
Perl doesn't impose restrictions on who gets to use which methods.
The public-versus-private distinction is by convention, not syntax.
-(Well, unless you use the Alias module described below in L</"Data Members
-as Variables">.) Occasionally you'll see method names beginning or ending
+(Well, unless you use the Alias module described below in
+L<Data Members as Variables>.) Occasionally you'll see method names beginning or ending
with an underscore or two. This marking is a convention indicating
that the methods are private to that class alone and sometimes to its
closest acquaintances, its immediate subclasses. But this distinction
There's no reason to limit methods to those that simply access data.
Methods can do anything at all. The key point is that they're invoked
against an object or a class. Let's say we'd like object methods that
-do more than fetch or set one particular field .
+do more than fetch or set one particular field.
sub exclaim {
my $self = shift;
return sprintf "Hi, I'm %s, age %d, working with %s",
- $self->{NAME}, $self->{AGE}, join(", ", $self->{PEERS});
+ $self->{NAME}, $self->{AGE}, join(", ", @{$self->{PEERS}});
}
Or maybe even one like this:
}
But since these methods are all executing in the class itself, this
-may not be critical. There are trade-offs to be made. Using direct
+may not be critical. There are tradeoffs to be made. Using direct
hash access is faster (about an order of magnitude faster, in fact), and
it's more convenient when you want to interpolate in strings. But using
methods (the external interface) internally shields not just the users of
Got that? Maybe not. Ok, let's say that some other class "borrowed"
(well, inherited) the DESTROY method as it was defined above. When those
-objects are destructed, the original $Census variable will be altered,
+objects are destroyed, the original $Census variable will be altered,
not the one in the new class's package namespace. Perhaps this is what
you want, but probably it isn't.
to remind ourselves that this field is special and not to be used as
a public data member in the same way that NAME, AGE, and PEERS are.
(Because we've been developing this code under the strict pragma, prior
-to 5.004 we'll have to quote the field name.)
+to perl version 5.004 we'll have to quote the field name.)
sub new {
my $proto = shift;
-- ${ $self->{"_CENSUS"} };
}
+What happens if a derived class (which we'll call Employee) inherits
+methods from this Person base class? Then C<< Employee->debug() >>, when called
+as a class method, manipulates $Person::Debugging not $Employee::Debugging.
+
=head2 Class Destructors
-The object destructor handles for each particular object. But sometimes
+The object destructor handles the death of each distinct object. But sometimes
you want a bit of cleanup when the entire class is shut down, which
currently only happens when the program exits. To make such a
I<class destructor>, create a function in that class's package named
then the new derived class can be used as a drop-in replacement for the
old one. This means you should be able to write a program like this:
- use Employee
+ use Employee;
my $empl = Employee->new();
$empl->name("Jason");
$empl->age(23);
methods access package data via that reference, so we should be ok.
What do we mean by the Person::new() function -- isn't that actually
-method. Well, in principle, yes. A method is just a function that
+a method? Well, in principle, yes. A method is just a function that
expects as its first argument a class name (package) or object
-(bless reference). Person::new() is the function that both the
-C<Person-E<gt>new()> method and the C<Employee-E<gt>new()> method end
+(blessed reference). Person::new() is the function that both the
+C<< Person->new() >> method and the C<< Employee->new() >> method end
up calling. Understand that while a method call looks a lot like a
function call, they aren't really quite the same, and if you treat them
as the same, you'll very soon be left with nothing but broken programs.
So don't use function calls when you mean to call a method.
If an employee is just a Person, that's not all too very interesting.
-So let's add some other methods. We'll give our employee
+So let's add some other methods. We'll give our employee
data fields to access their salary, their employee ID, and their
start date.
}
There, we've just demonstrated the high-falutin' concept known in certain
-circles as I<polymorphism>. We've taken on the form and behavior of
+circles as I<polymorphism>. We've taken on the form and behaviour of
an existing object, and then we've altered it to suit our own purposes.
This is a form of Laziness. (Getting polymorphed is also what happens
when the wizard decides you'd look better as a frog.)
Every now and then you'll want to have a method call trigger both its
-derived class (also know as "subclass") version as well as its base class
+derived class (also known as "subclass") version as well as its base class
(also known as "superclass") version. In practice, constructors and
destructors are likely to want to do this, and it probably also makes
sense in the debug() method we showed previously.
you inherit from, or add others. Fortunately, the pseudoclass SUPER
comes to the rescue here.
- $class->SUPER::debug($Debugging);
+ $self->SUPER::debug($Debugging);
This way it starts looking in my class's @ISA. This only makes sense
from I<within> a method call, though. Don't try to access anything
printf "His peers are: %s\n", join(", ", $boss->peers);
Running it, we see that we're still ok. If you'd like to dump out your
-object in a nice format, the way the 'x' command does in the debugger,
-you could use these undocumented calls the debugger employs (until
-its author changes them).
+object in a nice format, somewhat like the way the 'x' command works in
+the debugger, you could use the Data::Dumper module from CPAN this way:
- require 'dumpvar.pl';
+ use Data::Dumper;
print "Here's the boss:\n";
- dumpValue($boss);
+ print Dumper($boss);
Which shows us something like this:
- Boss=HASH(0x8104084)
- '_CENSUS' => SCALAR(0x80c949c)
- -> 1
- 'AGE' => 47
- 'FULLNAME' => Fullname=HASH(0x81040d8)
- 'CHRISTIAN' => 'Federico Miguel'
- 'NICK' => 'Fred'
- 'SURNAME' => 'Pichon Alvarez'
- 'TITLE' => 'Don'
- 'PEERS' => ARRAY(0x80ebb3c)
- 0 'Frank'
- 1 'Felipe'
- 2 'Faust'
+ Here's the boss:
+ $VAR1 = bless( {
+ _CENSUS => \1,
+ FULLNAME => bless( {
+ TITLE => 'Don',
+ SURNAME => 'Pichon Alvarez',
+ NICK => 'Fred',
+ CHRISTIAN => 'Federico Jesus'
+ }, 'Fullname' ),
+ AGE => 47,
+ PEERS => [
+ 'Frank',
+ 'Felipe',
+ 'Faust'
+ ]
+ }, 'Boss' );
Hm.... something's missing there. What about the salary, start date,
and ID fields? Well, we never set them to anything, even undef, so they
However, there is one particular area where MI in Perl is rampant:
borrowing another class's class methods. This is rather common,
-particularly with some bundled "objectless" classes,
+especially with some bundled "objectless" classes,
like Exporter, DynaLoader, AutoLoader, and SelfLoader. These classes
do not provide constructors; they exist only so you may inherit their
-class methods. (It's not entirey clear why inheritance was done
+class methods. (It's not entirely clear why inheritance was done
here rather than traditional module importation.)
For example, here is the POSIX module's @ISA:
Why don't people use MI for object methods much? One reason is that
it can have complicated side-effects. For one thing, your inheritance
graph (no longer a tree) might converge back to the same base class.
-Although Perl guards against recursive inheritance, but having parents
+Although Perl guards against recursive inheritance, merely having parents
who are related to each other via a common ancestor, incestuous though
it sounds, is not forbidden. What if in our Third class shown above we
wanted its new() method to also call both overridden constructors in its
having to go and add it to each and every @ISA. Well, it turns out that
you can. You don't see it, but Perl tacitly and irrevocably assumes
that there's an extra element at the end of @ISA: the class UNIVERSAL.
-In 5.003, there were no predefined methods there, but you could put
+In version 5.003, there were no predefined methods there, but you could put
whatever you felt like into it.
-However, as of 5.004 (or some subversive releases, like 5.003_08),
-UNIVERSAL has some methods in it already. These are built-in to your Perl
+However, as of version 5.004 (or some subversive releases, like 5.003_08),
+UNIVERSAL has some methods in it already. These are builtin to your Perl
binary, so they don't take any extra time to load. Predefined methods
include isa(), can(), and VERSION(). isa() tells you whether an object or
class "is" another one without having to traverse the hierarchy yourself:
$his_vers = $ob->VERSION();
However, we don't usually call VERSION ourselves. (Remember that an all
-upper-case function name is a Perl convention that indicates that the
+uppercase function name is a Perl convention that indicates that the
function will be automatically used by Perl in some way.) In this case,
it happens when you say
use Some_Module 3.0;
-If you wanted to add versioning to your Person class explained
+If you wanted to add version checking to your Person class explained
above, just add this to Person.pm:
- use vars qw($VERSION);
- $VERSION = '1.1';
+ our $VERSION = '1.1';
and then in Employee.pm could you can say
sub new {
my $self = [];
$self->[$NAME] = undef; # this is unnecessary
- $self->[$AGE] = undef; # as it this
+ $self->[$AGE] = undef; # as is this
$self->[$PEERS] = []; # but this isn't, really
bless($self);
return $self;
1; # so the require or use succeeds
-You might guess that the array access will be a lot faster than the
-hash access, but they're actually comparable. The array is a little
+You might guess that the array access would be a lot faster than the
+hash access, but they're actually comparable. The array is a I<little>
bit faster, but not more than ten or fifteen percent, even when you
replace the variables above like $AGE with literal numbers, like 1.
A bigger difference between the two approaches can be found in memory use.
A hash representation takes up more memory than an array representation
-because you have to allocation memory for the keys as well as the values.
-However, it really isn't that bad, especially since as of 5.004,
-memory is only allocated one for a given hash key, no matter how many
+because you have to allocate memory for the keys as well as for the values.
+However, it really isn't that bad, especially since as of version 5.004,
+memory is only allocated once for a given hash key, no matter how many
hashes have that key. It's expected that sometime in the future, even
these differences will fade into obscurity as more efficient underlying
representations are devised.
put the data into an anonymous hash that's lexically visible only to
the closure we create, bless, and return as the object. This object's
methods turn around and call the closure as a regular subroutine call,
-passing it as a particular argument the field we want to affect. (Yes,
+passing it the field we want to affect. (Yes,
the double-function call is slow, but if you wanted fast, you wouldn't
be using objects at all, eh? :-)
Because this object is hidden behind a code reference, it's probably a bit
mysterious to those whose background is more firmly rooted in standard
procedural or object-based programming languages than in functional
-procedural programming languages whence closures derive. The object
+programming languages whence closures derive. The object
created and returned by the new() method is itself not a data reference
as we've seen before. It's an anonymous code reference that has within
-it access to a particular version (lexical binding and instantiation)
+it access to a specific version (lexical binding and instantiation)
of the object's data, which are stored in the private variable $self.
Although this is the same function each time, it contains a different
version of $self.
-When a method like C<$him-E<gt>name("Jason") is called, its implicit
-zeroth argument is as the invoking object just as it is with all method
+When a method like C<$him-E<gt>name("Jason")> is called, its implicit
+zeroth argument is the invoking object--just as it is with all method
calls. But in this case, it's our code reference (something like a
function pointer in C++, but with deep binding of lexical variables).
There's not a lot to be done with a code reference beyond calling it, so
requested service. When used in this way, you may think
of autoloaded methods as "proxy" methods.
-When Perl tries to call an undefined function is a particular package
+When Perl tries to call an undefined function in a particular package
and that function is not defined, it looks for a function in
that same package called AUTOLOAD. If one exists, it's called
with the same arguments as the original function would have had.
we'll use the autoload mechanism to generate (actually, mimic) methods on
the fly. To verify that we're accessing a valid member, we will check
against an C<_permitted> (pronounced "under-permitted") field, which
-is a reference to a file-static hash of permitted fields in this record
+is a reference to a file-scoped lexical (like a C file static) hash of permitted fields in this record
called %fields. Why the underscore? For the same reason as the _CENSUS
field we once used: as a marker that means "for internal use only".
package Person;
use Carp;
- use vars qw($AUTOLOAD); # it's a package global
+ our $AUTOLOAD; # it's a package global
my %fields = (
name => undef,
Pretty nifty, eh? All we have to do to add new data fields
is modify %fields. No new functions need be written.
+I could have avoided the C<_permitted> field entirely, but I
+wanted to demonstrate how to store a reference to class data on the
+object so you wouldn't have to access that class data
+directly from an object method.
+
=head2 Inherited Autoloaded Data Methods
But what about inheritance? Can we define our Employee
package Employee;
use Person;
use strict;
- use vars qw(@ISA);
- @ISA = qw(Person);
+ our @ISA = qw(Person);
my %fields = (
id => undef,
we'll grab Person's version of that via inheritance,
and it will all work out just fine.
-=head1 Metaclass Tools
+=head1 Metaclassical Tools
Even though proxy methods can provide a more convenient approach to making
more struct-like classes than tediously coding up data methods as
Perl programmers have responded to this by creating several different
class construction classes. These metaclasses are classes
-that create other classes. Three worth looking at are
-Class::Template, Class::MethodMaker, and Alias. All can be
+that create other classes. A couple worth looking at are
+Class::Struct and Alias. These and other related metaclasses can be
found in the modules directory on CPAN.
-=head2 Class::Template
+=head2 Class::Struct
-One of the older ones is Class::Template. In fact, its syntax and
+One of the older ones is Class::Struct. In fact, its syntax and
interface were sketched out long before perl5 even solidified into a
-real thing. What it does is provide you a way to "declare"
-a class as having objects whose fields are of a particular type.
-The function that does this is called, not surprisingly
-enough, struct().
+real thing. What it does is provide you a way to "declare" a class
+as having objects whose fields are of a specific type. The function
+that does this is called, not surprisingly enough, struct(). Because
+structures or records are not base types in Perl, each time you want to
+create a class to provide a record-like data object, you yourself have
+to define a new() method, plus separate data-access methods for each of
+that record's fields. You'll quickly become bored with this process.
+The Class::Struct::struct() function alleviates this tedium.
Here's a simple example of using it:
- use Class::Template qw(struct);
+ use Class::Struct qw(struct);
use Jobbie; # user-defined; see below
struct 'Fred' => {
wanted to override Perl's idea of gethostbyname() and gethostbyaddr() so
that they would return objects that acted like C structures. We don't
care about high-falutin' OO gunk. All we want is for these objects to
-act like structs in the C sense.
+act like structs in the C sense.
use Socket;
use Net::hostent;
printf "perl.com's real name is %s, address %s\n",
$h->name, inet_ntoa($h->addr);
-Here's how to do this using the Class::Template module.
-They crux is going to be this call:
+Here's how to do this using the Class::Struct module.
+The crux is going to be this call:
- struct 'Net::hostent' => [
+ struct 'Net::hostent' => [ # note bracket
name => '$',
aliases => '@',
addrtype => '$',
We could also have implemented our object this way:
- struct 'Net::hostent' => {
+ struct 'Net::hostent' => { # note brace
name => '$',
aliases => '@',
addrtype => '$',
addr_list => '@',
};
-and then Class::Template would have used an anonymous hash as the object
+and then Class::Struct would have used an anonymous hash as the object
type, instead of an anonymous array. The array is faster and smaller,
but the hash works out better if you eventually want to do inheritance.
Since for this struct-like object we aren't planning on inheritance,
-we'll go for better speed and size over better flexibility.
+this time we'll opt for better speed and size over better flexibility.
Here's the whole implementation:
BEGIN {
use Exporter ();
- use vars qw(@ISA @EXPORT @EXPORT_OK %EXPORT_TAGS);
- @ISA = qw(Exporter);
- @EXPORT = qw(gethostbyname gethostbyaddr gethost);
- @EXPORT_OK = qw(
- $h_name @h_aliases
- $h_addrtype $h_length
- @h_addr_list $h_addr
- );
- %EXPORT_TAGS = ( FIELDS => [ @EXPORT_OK, @EXPORT ] );
+ our @EXPORT = qw(gethostbyname gethostbyaddr gethost);
+ our @EXPORT_OK = qw(
+ $h_name @h_aliases
+ $h_addrtype $h_length
+ @h_addr_list $h_addr
+ );
+ our %EXPORT_TAGS = ( FIELDS => [ @EXPORT_OK, @EXPORT ] );
}
- use vars @EXPORT_OK;
+ our @EXPORT_OK;
- use Class::Template qw(struct);
+ # Class::Struct forbids use of @ISA
+ sub import { goto &Exporter::import }
+
+ use Class::Struct qw(struct);
struct 'Net::hostent' => [
name => '$',
aliases => '@',
sub populate (@) {
return unless @_;
- my $hob = new(); # Class::Template made this!
+ my $hob = new(); # Class::Struct made this!
$h_name = $hob->[0] = $_[0];
@h_aliases = @{ $hob->[1] } = split ' ', $_[1];
$h_addrtype = $hob->[2] = $_[2];
We've snuck in quite a fair bit of other concepts besides just dynamic
class creation, like overriding core functions, import/export bits,
-function prototyping, and short-cut function call via C<&whatever>.
-These all mostly make sense from the perspective of a traditional module,
-but as you can see, we can also use them in an object module.
+function prototyping, short-cut function call via C<&whatever>, and
+function replacement with C<goto &whatever>. These all mostly make
+sense from the perspective of a traditional module, but as you can see,
+we can also use them in an object module.
You can look at other object-based, struct-like overrides of core
functions in the 5.004 release of Perl in File::stat, Net::hostent,
Net::netent, Net::protoent, Net::servent, Time::gmtime, Time::localtime,
User::grent, and User::pwent. These modules have a final component
-that's all lower-case, by convention reserved for compiler pragmas,
-because they affect the compilation and change a built-in function.
-They also have the type name that a C programmer would most expect.
+that's all lowercase, by convention reserved for compiler pragmas,
+because they affect the compilation and change a builtin function.
+They also have the type names that a C programmer would most expect.
=head2 Data Members as Variables
}
use Alias qw(attr);
- use vars qw($NAME $AGE $PEERS);
+ our ($NAME, $AGE, $PEERS);
sub name {
my $self = attr shift;
return ++$AGE;
}
-The need for the C<use vars> declaration is because what Alias does
+The need for the C<our> declaration is because what Alias does
is play with package globals with the same name as the fields. To use
-globals while C<use strict> is in effect, you have to pre-declare them.
+globals while C<use strict> is in effect, you have to predeclare them.
These package variables are localized to the block enclosing the attr()
call just as if you'd used a local() on them. However, that means that
they're still considered global variables with temporary values, just
as with any other local().
It would be nice to combine Alias with
-something like Class::Template or Class::MethodMaker.
+something like Class::Struct or Class::MethodMaker.
=head2 NOTES
For example, it's common to call an object an I<instance> of a class
and to call those objects' methods I<instance methods>. Data fields
-particular to each object are often called I<instance data> or <object
+peculiar to each object are often called I<instance data> or I<object
attributes>, and data fields common to all members of that class are
I<class data>, I<class attributes>, or I<static data members>.
-Also, I<base class>, I<generic class>, and I<subclass> all describe
+Also, I<base class>, I<generic class>, and I<superclass> all describe
the same notion, whereas I<derived class>, I<specific class>, and
-I<superclass> describe the other related one.
+I<subclass> describe the other related one.
C++ programmers have I<static methods> and I<virtual methods>,
-but Perl only has I<class methods> and I<object methods>.
+but Perl only has I<class methods> and I<object methods>.
Actually, Perl only has methods. Whether a method gets used
as a class or object method is by usage only. You could accidentally
-call a class method (one expecting a string argument) on an
+call a class method (one expecting a string argument) on an
object (one expecting a reference), or vice versa.
->From the C++ perspective, all methods in Perl are virtual.
+Z<>From the C++ perspective, all methods in Perl are virtual.
This, by the way, is why they are never checked for function
-prototypes in the argument list as regular built-in and user-defined
+prototypes in the argument list as regular builtin and user-defined
functions can be.
Because a class is itself something of an object, Perl's classes can be
taken as describing both a "class as meta-object" (also called I<object
factory>) philosophy and the "class as type definition" (I<declaring>
-behavior, not I<defining> mechanism) idea. C++ supports the latter
+behaviour, not I<defining> mechanism) idea. C++ supports the latter
notion, but not the former.
-=head2 Programming with Style
-
-Remember the underscores we used on "start_date" and "START_DATE"?
-While some programmers might be tempted to leave them out, please don't.
-Otherwise it's hard for some people to read. Also, you'd have to make
-up a new rule for identifiers that you've rendered in all capitals,
-like START_DATE. Plus you get people wondering whether it's "startdate",
-"Startdate", "startDate", "StartDate", or some other crazy variation.
-And adding another word, like "employee_start_date", just racks up the
-confusion. Nobody but a compiler wants to parse "employeestartdate" or
-even "EmployeeStartDate". So (almost) always use underscores to separate
-words in identifiers. See also L<perlstyle> and either L<perlmod> or the
-list of registered modules posted periodically to comp.lang.perl.modules
-or found on CPAN in the http://www.perl.com/CPAN/modules/ directory.
-
=head1 SEE ALSO
-The following man pages will doubtless provide more
+The following manpages will doubtless provide more
background for this one:
L<perlmod>,
L<perlref>,
and
L<overload>.
-=head1 COPYRIGHT
+=head1 AUTHOR AND COPYRIGHT
+
+Copyright (c) 1997, 1998 Tom Christiansen
+All rights reserved.
+
+When included as part of the Standard Version of Perl, or as part of
+its complete documentation whether printed or otherwise, this work
+may be distributed only under the terms of Perl's Artistic License.
+Any distribution of this file or derivatives thereof I<outside>
+of that package require that special arrangements be made with
+copyright holder.
-I I<really> hate to have to say this, but recent unpleasant
-experiences have mandated its inclusion:
-
- Copyright 1996 Tom Christiansen. All Rights Reserved.
-
-This work derives in part from the second edition of I<Programming Perl>.
-Although destined for release as a man page with the standard Perl
-distribution, it is not public domain (nor is any of Perl and its docset:
-publishers beware). It's expected to someday make its way into a revision
-of the Camel Book. While it is copyright by me with all rights reserved,
-permission is granted to freely distribute verbatim copies of this
-document provided that no modifications outside of formatting be made,
-and that this notice remain intact. You are permitted and encouraged to
-use its code and derivatives thereof in your own source code for fun or
-for profit as you see fit. But so help me, if in six months I find some
-book out there with a hacked-up version of this material in it claiming to
-be written by someone else, I'll tell all the world that you're a jerk.
-Furthermore, your lawyer will meet my lawyer (or O'Reilly's) over lunch
-to arrange for you to receive your just deserts. Count on it.
+Irrespective of its distribution, all code examples in this file
+are hereby placed into the public domain. You are permitted and
+encouraged to use this code in your own programs for fun
+or for profit as you see fit. A simple comment in the code giving
+credit would be courteous but is not required.
+
+=head1 COPYRIGHT
=head2 Acknowledgments
-Thanks to Brad Appleton, Raphael Manfredi, Dean Roehrich, Gurusamy
-Sarathy, and many others from the perl porters list for their helpful
-comments.
+Thanks to
+Larry Wall,
+Roderick Schertler,
+Gurusamy Sarathy,
+Dean Roehrich,
+Raphael Manfredi,
+Brent Halsey,
+Greg Bacon,
+Brad Appleton,
+and many others for their helpful comments.