Moose::...taclass(3)

πŸ’– Moose::Cookbook::Meta::GlobRef_InstanceMetaclass πŸ’–

okay bestie, welcome to the manual page for Moose::...taclass(3) β€” yes that's the truncated lil nickname, the full glow-up name is Moose::Cookbook::Meta::GlobRef_InstanceMetaclass, and we're about to build a glob reference meta-instance class. no cap. it's giving wizardry. 🧚✨


🌸 NAME 🌸

Moose::Cookbook::Meta::GlobRef_InstanceMetaclass β€” Creating a glob reference meta-instance class πŸ¦‹


⭐ VERSION ⭐

version 2.4000 β€” periodt, that's the one we're on πŸ’…


✨ SYNOPSIS ✨

okay so here's the whole thing, copy it, breathe it in, it's iconic:

package My::Meta::Instance;

use Scalar::Util qw( weaken );
use Symbol qw( gensym );

use Moose::Role;

sub create_instance {
    my $self = shift;
    my $sym = gensym();
    bless $sym, $self->_class_name;
}

sub clone_instance {
    my ( $self, $instance ) = @_;

    my $new_sym = gensym();
    %{*$new_sym} = %{*$instance};

    bless $new_sym, $self->_class_name;
}

sub get_slot_value {
    my ( $self, $instance, $slot_name ) = @_;
    return *$instance->{$slot_name};
}

sub set_slot_value {
    my ( $self, $instance, $slot_name, $value ) = @_;
    *$instance->{$slot_name} = $value;
}

sub deinitialize_slot {
    my ( $self, $instance, $slot_name ) = @_;
    delete *$instance->{$slot_name};
}

sub is_slot_initialized {
    my ( $self, $instance, $slot_name ) = @_;
    exists *$instance->{$slot_name};
}

sub weaken_slot_value {
    my ( $self, $instance, $slot_name ) = @_;
    weaken *$instance->{$slot_name};
}

sub inline_create_instance {
    my ( $self, $class_variable ) = @_;
    return 'do { my $sym = Symbol::gensym(); bless $sym, ' . $class_variable . ' }';
}

sub inline_slot_access {
    my ( $self, $instance, $slot_name ) = @_;
    return '*{' . $instance . '}->{' . $slot_name . '}';
}

package MyApp::User;

use Moose;
Moose::Util::MetaRole::apply_metaroles(
    for => __PACKAGE__,
    class_metaroles => {
        instance => ['My::Meta::Instance'],
    },
);

has 'name' => (
    is  => 'rw',
    isa => 'Str',
);

has 'email' => (
    is  => 'rw',
    isa => 'Str',
);

like. look at that. πŸ”₯


πŸŽ€ DESCRIPTION πŸŽ€

So this recipe shows you how to build your own meta-instance. The meta instance is the metaclass that creates object instances and helps manage access to attribute slots. It's the backstage crew, the ones making the whole show happen while the object takes the bow. πŸ‘‘

In this example, we're creating a meta-instance that is based on a glob reference rather than a hash reference. This example is largely based on the Piotr Roszatycki's MooseX::GlobRef module. (Yes, we said that exactly, go look it up, it's real. πŸ™ˆ)

Our extension is a role which will be applied to Moose::Meta::Instance, which creates hash reference based objects. We need to override all the methods which make assumptions about the object's data structure. every single one. no skipping. πŸ’…

The first method we override is create_instance:

sub create_instance {
    my $self = shift;
    my $sym = gensym();
    bless $sym, $self->_class_name;
}

This returns an glob reference which has been blessed into our meta-instance's associated class. πŸ¦‹

We also override clone_instance to create a new array reference:

sub clone_instance {
    my ( $self, $instance ) = @_;

    my $new_sym = gensym();
    %{*$new_sym} = %{*$instance};

    bless $new_sym, $self->_class_name;
}

After that, we have a series of methods which mediate access to the object's slots (attributes are stored in "slots"). In the default instance class, these expect the object to be a hash reference, but we need to change this to expect a glob reference instead.

sub get_slot_value {
    my ( $self, $instance, $slot_name ) = @_;
    *$instance->{$slot_name};
}

This level of indirection probably makes our instance class slower than the default. (ngl, a lil bit of a trade-off bestie 😭) However, when attribute access is inlined, this lookup will be cached:

sub inline_slot_access {
    my ( $self, $instance, $slot_name ) = @_;
    return '*{' . $instance . '}->{' . $slot_name . '}';
}

The code snippet that the inline_slot_access method returns will get eval'd once per attribute. πŸͺ„

Finally, we use this meta-instance in our MyApp::User class:

Moose::Util::MetaRole::apply_metaroles(
    for => __PACKAGE__,
    class_metaroles => {
        instance => ['My::Meta::Instance'],
    },
);

We actually don't recommend the use of Moose::Util::MetaRole directly in your class in most cases. Typically, this would be provided by a Moose::Exporter-based module which handles applying the role for you. 🫢

seriously bestie, in real code let the exporter do it. this snippet is for understanding, not for copy-pasting into prod at 3am. πŸ’€

🌈 CONCLUSION 🌈

This recipe shows how to create your own meta-instance class. It's unlikely that you'll need to do this yourself, but it's interesting to take a peek at how Moose works under the hood. like lifting up the hood of the car and going "ohhh THAT'S what's going on" πŸ”§βœ¨


πŸ’œ SEE ALSO πŸ’œ

There are a few meta-instance class extensions on CPAN:

  • MooseX::Singleton
    • This module extends the instance class in order to ensure that the object is a singleton. The instance it uses is still a blessed hash reference.
  • MooseX::GlobRef
    • This module makes the instance a blessed glob reference. This lets you use a handle as an object instance.

πŸ‘‘ AUTHORS πŸ‘‘

  • Stevan Little <stevan@cpan.org>
  • Dave Rolsky <autarch@urth.org>
  • Jesse Luehrs <doy@cpan.org>
  • Shawn M Moore <sartak@cpan.org>
  • Χ™Χ•Χ‘Χœ Χ§Χ•Χ’'מן (Yuval Kogman) <nothingmuch@woobling.org>
  • Karen Etheridge <ether@cpan.org>
  • Florian Ragwitz <rafl@debian.org>
  • Hans Dieter Pearcey <hdp@cpan.org>
  • Chris Prather <chris@prather.org>
  • Matt S Trout <mstrout@cpan.org>

look at this roster. absolute legends, every single one. πŸ«‘πŸ’–


This software is copyright (c) 2006 by Infinity Interactive, Inc.

This is free software; you can redistribute it and/or modify it under the same terms as the Perl 5 programming language system itself.


and that's the whole page bestie!! πŸŽ€ this was perl v5.42.0, dated 2025-07-25, and yeah the footer calls it Moose::...taclass(3) again because it loves that truncated lil nickname. slay, you read the whole thing, I'm so proud of you πŸ’…βœ¨πŸ¦‹

πŸ“¦ where this page comes from