arg, Makefile.PL/README updates, not critical
Brandon L Black [Mon, 4 Jun 2007 05:28:57 +0000 (05:28 +0000)]
Makefile.PL
README

index 6d5529a..4d34cb4 100644 (file)
@@ -1,11 +1,11 @@
-use inc::Module::Install;
+use inc::Module::Install 0.65;
 
 name           'Class-C3';
 all_from       'lib/Class/C3.pm';
 
 # Class::C3 under 5.9.5+ has no deps
 if($] < 5.009_005) {
-    build_requires 'Test::More'    => '0.47';
+    test_requires 'Test::More'    => '0.47';
 
     feature 'XS Speedups', 'Class::C3::XS' => '0.07';
 
@@ -14,5 +14,11 @@ if($] < 5.009_005) {
     requires 'Scalar::Util'  => '1.10';
 }
 
+# Rebuild README for maintainers
+if(-e 'MANIFEST.SKIP') {
+    system("pod2text lib/Class/C3.pm >README");
+}
+
+auto_provides;
 auto_install;
 WriteAll;
diff --git a/README b/README
index 4ce9db5..00290fb 100644 (file)
--- a/README
+++ b/README
-Class::C3 version 0.18
-===========================
+NAME
+    Class::C3 - A pragma to use the C3 method resolution order algortihm
 
-INSTALLATION
+SYNOPSIS
+        package A;
+        use Class::C3;     
+        sub hello { 'A::hello' }
 
-To install this module type the following:
+        package B;
+        use base 'A';
+        use Class::C3;     
 
-   perl Makefile.PL
-   make
-   make test
-   make install
+        package C;
+        use base 'A';
+        use Class::C3;     
 
-DEPENDENCIES
+        sub hello { 'C::hello' }
 
-This module requires these other modules and libraries:
+        package D;
+        use base ('B', 'C');
+        use Class::C3;    
 
-       Algorithm::C3 0.06
-       Scalar::Util 1.10
+        # Classic Diamond MI pattern
+        #    <A>
+        #   /   \
+        # <B>   <C>
+        #   \   /
+        #    <D>
 
-Additionally, this module will optionally take advantage of
-these if installed:
+        package main;
+    
+        # initializez the C3 module 
+        # (formerly called in INIT)
+        Class::C3::initialize();  
 
-        perl 5.9.5
-        Class::C3::XS 0.04
+        print join ', ' => Class::C3::calculateMRO('Diamond_D') # prints D, B, C, A
 
-COPYRIGHT AND LICENCE
+        print D->hello() # prints 'C::hello' instead of the standard p5 'A::hello'
+    
+        D->can('hello')->();          # can() also works correctly
+        UNIVERSAL::can('D', 'hello'); # as does UNIVERSAL::can()
 
-Copyright (C) 2005, 2006 Infinity Interactive, Inc.
+DESCRIPTION
+    This is pragma to change Perl 5's standard method resolution order from
+    depth-first left-to-right (a.k.a - pre-order) to the more sophisticated
+    C3 method resolution order.
 
-http://www.iinteractive.com
+  What is C3?
+    C3 is the name of an algorithm which aims to provide a sane method
+    resolution order under multiple inheritence. It was first introduced in
+    the langauge Dylan (see links in the "SEE ALSO" section), and then later
+    adopted as the prefered MRO (Method Resolution Order) for the new-style
+    classes in Python 2.3. Most recently it has been adopted as the
+    'canonical' MRO for Perl 6 classes, and the default MRO for Parrot
+    objects as well.
 
-This library is free software; you can redistribute it and/or modify
-it under the same terms as Perl itself. 
+  How does C3 work.
+    C3 works by always preserving local precendence ordering. This
+    essentially means that no class will appear before any of it's
+    subclasses. Take the classic diamond inheritence pattern for instance:
+
+         <A>
+        /   \
+      <B>   <C>
+        \   /
+         <D>
+
+    The standard Perl 5 MRO would be (D, B, A, C). The result being that A
+    appears before C, even though C is the subclass of A. The C3 MRO
+    algorithm however, produces the following MRO (D, B, C, A), which does
+    not have this same issue.
+
+    This example is fairly trival, for more complex examples and a deeper
+    explaination, see the links in the "SEE ALSO" section.
+
+  How does this module work?
+    This module uses a technique similar to Perl 5's method caching. When
+    "Class::C3::initialize" is called, this module calculates the MRO of all
+    the classes which called "use Class::C3". It then gathers information
+    from the symbol tables of each of those classes, and builds a set of
+    method aliases for the correct dispatch ordering. Once all these
+    C3-based method tables are created, it then adds the method aliases into
+    the local classes symbol table.
+
+    The end result is actually classes with pre-cached method dispatch.
+    However, this caching does not do well if you start changing your @ISA
+    or messing with class symbol tables, so you should consider your classes
+    to be effectively closed. See the CAVEATS section for more details.
+
+OPTIONAL LOWERCASE PRAGMA
+    This release also includes an optional module c3 in the opt/ folder. I
+    did not include this in the regular install since lowercase module names
+    are considered *"bad"* by some people. However I think that code looks
+    much nicer like this:
+
+      package MyClass;
+      use c3;
+  
+    The the more clunky:
+
+      package MyClass;
+      use Class::C3;
+  
+    But hey, it's your choice, thats why it is optional.
+
+FUNCTIONS
+    calculateMRO ($class)
+        Given a $class this will return an array of class names in the
+        proper C3 method resolution order.
+
+    initialize
+        This must be called to initalize the C3 method dispatch tables, this
+        module will not work if you do not do this. It is advised to do this
+        as soon as possible after loading any classes which use C3. Here is
+        a quick code example:
+
+          package Foo;
+          use Class::C3;
+          # ... Foo methods here
+  
+          package Bar;
+          use Class::C3;
+          use base 'Foo';
+          # ... Bar methods here
+  
+          package main;
+  
+          Class::C3::initialize(); # now it is safe to use Foo and Bar
+
+        This function used to be called automatically for you in the INIT
+        phase of the perl compiler, but that lead to warnings if this module
+        was required at runtime. After discussion with my user base (the
+        DBIx::Class folks), we decided that calling this in INIT was more of
+        an annoyance than a convience. I apologize to anyone this causes
+        problems for (although i would very suprised if I had any other
+        users other than the DBIx::Class folks). The simplest solution of
+        course is to define your own INIT method which calls this function.
+
+        NOTE:
+
+        If "initialize" detects that "initialize" has already been executed,
+        it will "uninitialize" and clear the MRO cache first.
+
+    uninitialize
+        Calling this function results in the removal of all cached methods,
+        and the restoration of the old Perl 5 style dispatch order
+        (depth-first, left-to-right).
+
+    reinitialize
+        This is an alias for "initialize" above.
+
+METHOD REDISPATCHING
+    It is always useful to be able to re-dispatch your method call to the
+    "next most applicable method". This module provides a pseudo package
+    along the lines of "SUPER::" or "NEXT::" which will re-dispatch the
+    method along the C3 linearization. This is best show with an examples.
+
+      # a classic diamond MI pattern ...
+         <A>
+        /   \
+      <B>   <C>
+        \   /
+         <D>
+  
+      package A;
+      use c3; 
+      sub foo { 'A::foo' }       
+      package B;
+      use base 'A'; 
+      use c3;     
+      sub foo { 'B::foo => ' . (shift)->next::method() }       
+      package B;
+      use base 'A'; 
+      use c3;    
+      sub foo { 'C::foo => ' . (shift)->next::method() }   
+      package D;
+      use base ('B', 'C'); 
+      use c3; 
+      sub foo { 'D::foo => ' . (shift)->next::method() }   
+  
+      print D->foo; # prints out "D::foo => B::foo => C::foo => A::foo"
+
+    A few things to note. First, we do not require you to add on the method
+    name to the "next::method" call (this is unlike "NEXT::" and "SUPER::"
+    which do require that). This helps to enforce the rule that you cannot
+    dispatch to a method of a different name (this is how "NEXT::" behaves
+    as well).
+
+    The next thing to keep in mind is that you will need to pass all
+    arguments to "next::method" it can not automatically use the current @_.
+
+    If "next::method" cannot find a next method to re-dispatch the call to,
+    it will throw an exception. You can use "next::can" to see if
+    "next::method" will succeed before you call it like so:
+
+      $self->next::method(@_) if $self->next::can; 
+
+    Additionally, you can use "maybe::next::method" as a shortcut to only
+    call the next method if it exists. The previous example could be simply
+    written as:
+
+      $self->maybe::next::method(@_);
+
+    There are some caveats about using "next::method", see below for those.
+
+CAVEATS
+    This module used to be labeled as *experimental*, however it has now
+    been pretty heavily tested by the good folks over at DBIx::Class and I
+    am confident this module is perfectly usable for whatever your needs
+    might be.
+
+    But there are still caveats, so here goes ...
+
+    Use of "SUPER::".
+        The idea of "SUPER::" under multiple inheritence is ambigious, and
+        generally not recomended anyway. However, it's use in conjuntion
+        with this module is very much not recommended, and in fact very
+        discouraged. The recommended approach is to instead use the supplied
+        "next::method" feature, see more details on it's usage above.
+
+    Changing @ISA.
+        It is the author's opinion that changing @ISA at runtime is pure
+        insanity anyway. However, people do it, so I must caveat. Any
+        changes to the @ISA will not be reflected in the MRO calculated by
+        this module, and therefor probably won't even show up. If you do
+        this, you will need to call "reinitialize" in order to recalulate
+        all method dispatch tables. See the "reinitialize" documentation and
+        an example in t/20_reinitialize.t for more information.
+
+    Adding/deleting methods from class symbol tables.
+        This module calculates the MRO for each requested class by
+        interogatting the symbol tables of said classes. So any symbol table
+        manipulation which takes place after our INIT phase is run will not
+        be reflected in the calculated MRO. Just as with changing the @ISA,
+        you will need to call "reinitialize" for any changes you make to
+        take effect.
+
+    Calling "next::method" from methods defined outside the class
+        There is an edge case when using "next::method" from within a
+        subroutine which was created in a different module than the one it
+        is called from. It sounds complicated, but it really isn't. Here is
+        an example which will not work correctly:
+
+          *Foo::foo = sub { (shift)->next::method(@_) };
+
+        The problem exists because the anonymous subroutine being assigned
+        to the glob *Foo::foo will show up in the call stack as being called
+        "__ANON__" and not "foo" as you might expect. Since "next::method"
+        uses "caller" to find the name of the method it was called in, it
+        will fail in this case.
+
+        But fear not, there is a simple solution. The module "Sub::Name"
+        will reach into the perl internals and assign a name to an anonymous
+        subroutine for you. Simply do this:
+
+          use Sub::Name 'subname';
+          *Foo::foo = subname 'Foo::foo' => sub { (shift)->next::method(@_) };
+
+        and things will Just Work. Of course this is not always possible to
+        do, but to be honest, I just can't manage to find a workaround for
+        it, so until someone gives me a working patch this will be a known
+        limitation of this module.
+
+COMPATIBILITY
+    If your software requires Perl 5.9.5 or higher, you do not need
+    Class::C3, you can simply "use mro 'c3'", and not worry about
+    "initialize()", avoid some of the above caveats, and get the best
+    possible performance. See mro for more details.
+
+    If your software is meant to work on earlier Perls, use Class::C3 as
+    documented here. Class::C3 will detect Perl 5.9.5+ and take advantage of
+    the core support when available.
+
+Class::C3::XS
+    This module will load Class::C3::XS if it's installed and you are
+    running on a Perl version older than 5.9.5. Installing this is
+    recommended when possible, as it results in significant performance
+    improvements (but unlike the 5.9.5+ core support, it still has all of
+    the same caveats as Class::C3).
+
+CODE COVERAGE
+    Devel::Cover was reporting 94.4% overall test coverage earlier in this
+    module's life. Currently, the test suite does things that break under
+    coverage testing, but it is fair to assume the coverage is still close
+    to that value.
+
+SEE ALSO
+  The original Dylan paper
+    <http://www.webcom.com/haahr/dylan/linearization-oopsla96.html>
+
+  The prototype Perl 6 Object Model uses C3
+    <http://svn.openfoundry.org/pugs/perl5/Perl6-MetaModel/>
+
+  Parrot now uses C3
+    <http://aspn.activestate.com/ASPN/Mail/Message/perl6-internals/2746631>
+    <http://use.perl.org/~autrijus/journal/25768>
+
+  Python 2.3 MRO related links
+    <http://www.python.org/2.3/mro.html>
+    <http://www.python.org/2.2.2/descrintro.html#mro>
+
+  C3 for TinyCLOS
+    <http://www.call-with-current-continuation.org/eggs/c3.html>
+
+ACKNOWLEGEMENTS
+    Thanks to Matt S. Trout for using this module in his module DBIx::Class
+    and finding many bugs and providing fixes.
+    Thanks to Justin Guenther for making "next::method" more robust by
+    handling calls inside "eval" and anon-subs.
+    Thanks to Robert Norris for adding support for "next::can" and
+    "maybe::next::method".
+
+AUTHOR
+    Stevan Little, <stevan@iinteractive.com>
+
+    Brandon L. Black, <blblack@gmail.com>
+
+COPYRIGHT AND LICENSE
+    Copyright 2005, 2006 by Infinity Interactive, Inc.
+
+    <http://www.iinteractive.com>
+
+    This library is free software; you can redistribute it and/or modify it
+    under the same terms as Perl itself.