=encoding utf8

=head1 NAME

perl5i::Meta - The perl5i meta object


=head1 SYNOPSIS

    use perl5i;

    my $id      = $object->mo->id;
    my $class   = $object->mc->class;
    my $tainted = $object->mo->is_tainted;
    ...and so on...


=head1 DESCRIPTION

Each object has a meta object which can be used to describe and
sometimes alter the object.  This is for things which are common to
*all* objects.  For example, C<< $obj->mc->class >> to get the
object's class.  C<< @ISA = $obj->mc->ISA >> to get an object's
parents.  And so on.


=head2 Why a meta object?

Why not just stick these methods in UNIVERSAL?  They'd clash with
user-space methods.  For example, if an existing class has its own
C<id()> method it would likely clash with what our C<id()> method
does.  You want to guarantee that every object responds to these meta
methods the same way so there's no second-guessing.


=head2 Meta Instance vs Meta Class

Each object has a meta object for their instance, accessible with C<<
$obj->mo >> and also a meta object for their class, accessible with
C<< $obj->mc >>.  The meta instance can do most everything the meta
class can, mc is provided mostly for disambiguation.

The problem is this:

    my $thing = "Foo";
    say $thing->mo->class;

In perl5i, everything is an object.  Do you want the class of $thing
or do you want to treat $thing as a class name?  Its ambiguous.  So to
disambiguate, use C<< $thing->mc >> when you mean $thing to be a class
name and C<< $thing->mo >> when you mean it to be an object.

For example, when writing a method which could be a class or could be
an object be sure to use C<< $proto->mc->class >> to get the class
name.

    sub my_method {
        my $proto = shift;  # could be an object, could be a class name
        my $class = $proto->mc->class;
        ....
    }


=head1 METHODS

=head3 id

    my $id = $object->mo->id;

Returns an identifier for $object.

The identifier is guaranteed to be:

  * unique to the object for the life of the process
  * a true value
  * independent of changes to the object's contents

=head3 class

    my $class = $object->mo->class;
    my $class = $class->mc->class;

Returns the class of the $object or $class.

=head3 ISA

    my @ISA = $object->mo->ISA;
    my @ISA = $class->mc->ISA;

Returns the immediate parents of the C<$class> or C<$object>.

Essentially equivalent to:

    no strict 'refs';
    my @ISA = @{$class.'::ISA'};


=head3 linear_isa

    my @isa = $class->mc->linear_isa();
    my @isa = $object->mo->linear_isa();

Returns the entire inheritance tree of the $class or $object as a list
in the order it will be searched for method inheritance.

This list includes the $class itself and includes UNIVERSAL.  For example:

    package Child;
    use parent qw(Parent);

    # Child, Parent, UNIVERSAL
    my @isa = Child->mo->linear_isa();


=head3 methods

    my @methods = $class->mc->methods;
    my $methods = $class->mc->methods;
    my @methods = $object->mo->methods;
    my $methods = $object->mo->methods;

    my $methods = $object->mo->methods({
        with_UNIVERSAL  => 0,
        just_mine       => 1,
    });

Returns the methods available to a $class or $object.

By default it returns all the methods available B<except those
inherited from UNIVERSAL> because you usually don't want to know that.

C<with_UNIVERSAL>, if true, makes it include methods inherited from UNIVERSAL.
It defaults to false.

C<just_mine>, if true, returns only methods defined in the $class.
It defaults to false.


=head3 symbol_table

    my $table = $class->mc->symbol_table;
    my $table = $obj->mo->symbol_table;

Returns the symbol table for the given $class or class of the $object.

If you don't know what a symbol table is... good.  If you really want to
know, see L<perldata/Typeglobs and FileHandles>.


=head3 super

    my @return = $class->mc->super(@args);
    my @return = $object->mo->super(@args);

Call the parent of $class/$object's implementation of the current method.

Equivalent to C<< $object->SUPER::method(@args) >> but based on the
class of the $object rather than the class in which the current method
was declared.


=head3 is_tainted

    my $is_tainted = $object->mo->is_tainted;

Returns true if the $object is tainted.

Only scalars can be tainted, so objects generally return false.

String and numerically overloaded objects will check against their
overloaded versions.


=head3 taint

    $object->mo->taint;

Taints the $object.

Normally only scalars can be tainted, this will throw an exception on
anything else.

Tainted, string overloaded objects will cause this to be a no-op.

An object can override this method if they have a means of tainting
themselves.  Generally this is applicable to string or numeric
overloaded objects who can taint their overloaded value.


=head3 untaint

    $object->mo->untaint;

Untaints the $object.

Normally objects cannot be tainted, so it is a no op on anything but a
scalar.

Tainted, string overloaded objects will throw an exception.

An object can override this method if they have a means of untainting
themselves.  Generally this is applicable to string or numeric
overloaded objects who can untaint their overloaded value.


=head3 reftype

    my $reftype = $object->mo->reftype;

Returns the underlying reference type of the $object.

=head3 checksum

    my $checksum = $object->mo->checksum;
    my $md5    = $object->mo->checksum( algorithm => 'md5' );
    my $base64 = $object->mo->checksum( format => 'base64' );

Get a digest of the object's contents, taking its class into account.

Two different objects can have the same checksum if their contents
are identical. Likewise, a single object can have different checksums
throughout its life cycle if it's mutable. This means its checksum
will change if its internal state changes.

For example,

    $obj->mo->checksum( format => 'base64', algorithm => 'md5' );

=head3 options

=over 4

=item algorithm

The checksum algorithm.  Can be C<sha1> and C<md5>.

Defaults to sha1.

=item format

The character set of the checksum, can be C<hex>, C<base64>, or
C<binary>.

Defaults to hex.

=back

=head3 is_equal

    $object->mo->is_equal($other_object)

Assess whether something is equal to something else, recurring over deep
data structures and treating overloaded objects as numbers or strings
when appropriate.

Examples:

    my $prices = { chair => 50, table => 300 };
    my $other  = { chair => 50, table => [250, 255] };

    say "They are equal" if $prices->mo->is_equal($other);


    my $uri = URI->new("http://www.perl.org");
    $uri->mo->is_equal("http://www.perl.org") # True

=head3 perl

Same as L<as_perl>.  For backwards compatibility.

=head3 as_perl

    my $dump = $object->mo->as_perl;

Dumps the contents of the $object as Perl in a string, like Data::Dumper.

=head3 as_json

    my $json = $object->mo->as_json;

Return the contents of the $object as JSON.

=head3 as_yaml

    my $json = $object->mo->as_yaml;

Return the contents of the $object as YAML.

=head3 dump

    my $dump = $object->mo->dump( format => $format );

Dumps the contents of the $object as a string in whatever format you like.

Possible formats are yaml, json and perl.

$format defaults to "perl" which is equivalent to C<< $object->mo->perl >>.

This is simply the long form of C<as_perl>, C<as_json> and C<as_yaml>.