MultiType(3pm)
π Object::MultiType π
okay bestie, sit down, hydrate, because this one is iconic. Object::MultiType (a Perl module, yes, the 3pm one) gives you an object that lowkey lives its whole double life: it acts like a Hash, an Array, a Scalar, a Code ref and a Glob β all at the same motherflipping time. one object, five personalities, main character energy fr fr. π
this page is long so it's coming to you in parts β part 1 starts right here, don't go anywhere.
β¨ SYNOPSIS β¨
here's the vibe:
use Object::MultiType ;
my $scalar = 'abc' ;
my @array = qw(x y z);
my %hash = (A => 1 , B => 2) ;
my $obj = Object::MultiType->new(
scalar => \$scalar ,
array => \@array ,
hash => \%hash ,
code => sub{ return("I'm a sub ref!") ; }
glob => \*STDOUT ,
) ;
print "Me as scalar: $obj\n" ;
my $array_1 = $obj->[1] ;
print "$array_1\n" ;
my $hash_B = $obj->{B} ;
print "$hash_B\n" ;
my $hash = $$obj->hash ;
foreach my $Key (sort keys %$hash ) {
print "$Key = $$hash{$Key}\n" ;
}
&$obj(args) ;
likeβ¦ she does every job at once and she does NOT miss. π
πΈ DESCRIPTION πΈ
This module hands you back an object that behaves like a Hash, an Array, a Scalar, a Code and a Glob object at the same time. no cap.
The usual way to use it is to call it from your own module's new():
package FOO ;
use Object::MultiType ;
use vars qw(@ISA) ;
@ISA = qw(Object::MultiType) ; ## Is good to 'Object::MultiType' be the last in @ISA!
sub new {
my $class = shift ;
my $this = Object::MultiType->new() ;
bless($this,$class) ;
}
heads up: it's good to have'Object::MultiType'be the last thing in@ISA! (that's literally what the comment says, so bestie, listen to her) π«Ά
π METHODS π
** ** Also go look at the methods of the Saver, bestie β see the Saver too.
π new
Arguments:
boolβ the boolean reference. Default:undefboolcode|boolsubβ set the sub/function (a CODE reference) that will return/generate the boolean value.scalarβ the SCALAR reference. If you don't send one, a null SCALAR gets created for you.scalarcode|scalarsubβ set the sub/function (a CODE reference) that will return/generate the scalar data of the object.arrayβ the ARRAY reference. If you don't send one, a null ARRAY gets created.hashβ the HASH reference. If you don't send one, a null HASH gets created.codeβ the CODE reference. If you don't send one, a nullsub{}gets created.
with this your object can be used as a sub reference:
my $multi = Object::MultiType->new( code => sub { print "Args: @_\n" ;} ) ;
&$multi();
note that the first argument sent to the SUB is the object ($multi).
globβ the GLOB (HANDLE) reference. If you don't send one, a null GLOB gets created.
** ** big warning: you can't actually use that default (null) GLOB that gets created when you don't pass this argument! because every single object will share it β it's literally only there so you don't get errors. so like, don't rely on it. π
tiearrayβ package name to create a TIEARRAY. The argument$$thisis sent totie().
tie() is called as:
tie(@array,$args{tiearray},$$this) ;
heads up: implementing the tie methods for PUSH, POP, SHIFT, UNSHIFT, SPLICE... is hard. unless you're just making an alias to another array through the tie methods. π
** ** see tiehash too.
tiehashβ package name to create a TIEHASH. The argument$$thisis sent totie().
tie() is called as:
tie(%hash,$args{tiehash},$$this) ;
** $$this (the Saver) is what gets sent, not $this β that's so DESTROY doesn't break (the auto reference thing). periodt.
** $$this is a reference to the Saver object that saves the SCALAR, ARRAY, HASH, CODE and GLOB.
sub TIEHASH {
my $class = shift ;
my $multi = shift ; ## $$this
my $scalarref = $multi->scalar ; ## \${*$multi}
my $arrayref = $multi->array ; ## \@{*$multi}
my $hashref = $multi->hash ; ## \%{*$multi}
my $this = { s => $scalarref , a => $arrayref , h => $hashref } ;
bless($this,$class) ;
}
tiehandleβ makes the object work like a tied glob (TIEHANDLE).
if used with glob it will tie() it. if glob isn't sent, a NULL GLOB is used:
my $multi = Object::MultiType->new(
glob => \*MYOUT , ## 'glob' is Optional.
tiehandle => 'TieHandlePack' ,
) ;
tieonuseβ the reference is only tied when it's used! so the HASH, ARRAY or GLOB (handle) only gets tied if/when they're accessed. lazy queen behavior, we respect it. πnodefaultβ if set to true, this tells it not to create the default references inside the Saver, and it'll only have the references you passed in (scalar,array,hash,code,glob).
** this is good for saving memory! π«Ά
is_saver
Returns 0. handy for checking whether the thing you're holding is the Saver or the MultiType object.
π SAVER π
The MultiType object has a Saver object (Object::MultiType::Saver) that saves all the different data types (references). You can get at this saver from the main object:
my $multi = Object::MultiType->new() ;
my $saver = $$multi ;
print $saver->scalar ;
so if you want to save attributes in your Object and you're using tiehash, you cannot set attributes directly on the MultiType object! like:
sub new {
my $class = shift ;
my $this = Object::MultiType->new(tiehash => 'TieHashPack') ;
## Dont do that! This will call the STORE() at TIEHASH, and not save it in the object:
$this->{flagx} = 1 ;
bless($this,$class) ;
}
so, if you use tiehash and still want to save attributes (outside the tie), do this instead:
## This save the attribute inside the Saver:
$$this->{flagx} = 1 ;
note that this sets an attribute in the saver, and the saver has its own attributes! slay:
## $saver = $$this ;
$saver->{s} ## the sacalar ref.
$saver->{a} ## the array ref.
$saver->{h} ## the hash ref.
$saver->{c} ## the code ref.
$saver->{g} ## the glob ref.
** ** go see "Direct access to the data types".
π DESTROY π
When the object gets DESTROYed, the Saver inside it gets cleaned, so the tied objects can get DESTROYed automatically too. clean girlie behavior. β¨
π¦ Direct access to the data types π¦
To access the reference of the different data types (SCALAR, ARRAY, HASH, CODE & GLOB) directly, use:
my $multi = Object::MultiType->new() ;
my $saver = $$multi ;
my $scalarref = $saver->scalar ; ## $saver->{s}
my $arrayref = $saver->array ; ## $saver->{a}
my $hashref = $saver->hash ; ## $saver->{h}
my $coderef = $saver->code ; ## $saver->{c}
my $globeref = $saver->glob ; ## $saver->{g}
## You can access the Saver directly from the main object:
$$multi->hash ;
Setting the data:
$saver->set_bool( 1 ) ;
$saver->set_scalar( 'xyz' ) ;
$saver->set_array( [qw(x y z)] ) ;
$saver->set_hash( {X => 1} ) ;
$saver->set_code( sub{ print "XYZ\n" ; } ) ;
$saver->set_glob( \*STDOUT ) ;
π As SCALAR π
You can use it as a SCALAR when you put it inside quotes or make a copy of it:
my $multi = Object::MultiType->new( scalar => 'Foo' ) ;
## Quote:
print "Me as scalar: $multi\n" ;
## Copy:
my $str = $multi ;
$str .= '_x' ; ## Copy made when you change it! Until that $str works like $multi.
print "$str\n" ;
using the argument scalarsub, you can use a function that generates the scalar data instead of a reference to a SCALAR:
my $multi = Object::MultiType->new(scalarsub => sub{ return 'generated data' ;} ) ;
print "My scalar have $multi!\n" ;
β As ARRAY β
You can use it as an ARRAY directly from the object:
my $multi = Object::MultiType->new( array => [qw(FOO BAR)] ) ;
my $array_0 = $multi->[0] ;
$multi->[1] = 'foo' ;
π As HASH π
You can use it as a HASH directly from the object:
my $multi = Object::MultiType->new( hash => {key => 'foo'} ) ;
my $k = $multi->{key} ;
$multi->{foo} = 'bar' ;
π§ With TIE π§
To use your ARRAY and HASH part tied, you can either pass in the already-tied reference of the HASH or ARRAY, or use the arguments tiehash and tiearray at new():
## Using the reference:
my %hash ;
tie(%hash,'TieHash') ;
my $multi = Object::MultiType->new(hash => \%hash) ;
## Or using directly the argument:
my $multi = Object::MultiType->new(tiehash => 'TieHashPack') ;
note that using tiehash or tiearray is better, because your tied HASH or ARRAY can see the object Saver and the other data types of it. go see the method new() and its arguments.
Here's an example of a TieHash package that gets called from Object::MultiType->new():
## The call inside Object::MultiType->new():
tie(%hash,$args{tiehash},$$this) ;
## The package:
package TieHash ;
sub TIEHASH {
my $class = shift ;
my $Saver = shift ; ## Object::MultiType paste as $$this (only the Saver) to avoid break of DESTROY!
## $this = Object::MultiType >> $$this = Object::MultiType::Saver
my $scalarref = $Saver->scalar ;
my $arrayref = $Saver->array ;
## Note that $Saver->hash will return the tied hash, and is not needed here!
## my $hashref = $Saver->hash ;
## Saving the references inside the TIE object:
my $this = { scalar => $scalarref , array => $arrayref , hash => {} } ;
bless($this,$class) ;
}
sub FETCH { my $this = shift ; return( 'key' ) ;}
sub NEXTKEY { my $this = shift ; return( 'key' ) ;}
sub STORE { my $this = shift ; $this->{hash}{$_[0]} = $_[1] }
sub DELETE { my $this = shift ; delete $this->{hash}{$_[0]} }
sub CLEAR { my $this = shift ; $this->{hash} = {} ;}
sub EXISTS { my $this = shift ; defined $this->{hash}{$_[0]} ;}
sub FIRSTKEY { my $this = shift ; (sort keys %{$this->{hash}} )[0] }
sub DESTROY {}
Using tiehash, you need to save the attributes in the Saver, otherwise you end up calling the tie():
$$this->{flagx} = 1 ;
π Object::MultiType::Saver π
This is a litte package where the Saver objects are created. It saves the data types (SCALAR, ARRAY, HASH, CODE & GLOB) of the main objects (Object::MultiType).
METHODS:
is_saver
Returns 1. handy for checking whether the thing you're holding is the Saver or the MultiType object.
bool
Returns the BOOL reference inside the Saver.
scalar
Returns the SCALAR reference inside the Saver.
array
Returns the ARRAY reference inside the Saver.
hash
Returns the HASH reference inside the Saver.
code
Returns the CODE/sub reference inside the Saver.
glob
Returns the GLOB/HANDLE reference inside the Saver.
set_bool
Sets the boolean reference inside the Saver.
set_scalar
Sets the SCALAR reference inside the Saver.
set_array
Sets the ARRAY reference inside the Saver.
set_hash
Sets the HASH reference inside the Saver.
set_code
Sets the CODE/sub reference inside the Saver.
set_glob
Sets the GLOB/HANDLE reference inside the Saver.
clean
Cleans all the references saved in the Saver. β¨
π SEE ALSO π
okay bestie, if you wanna go deeper, these are the gatekeepers you should go visit:
overloadβ the whole reason this module can even do the transformation thing. go read it, it's giving backstage pass β¨perltieβ for all the tie magic, iykyk πScalar::Utilβ the little toolkit that keeps things real π¦
π AUTHOR π
Graciliano M. P. <gm@virtuasites.com.br> β the icon, the legend, the main character who made this whole thing happen π
and fr fr, he says: "I will appreciate any type of feedback (include your opinions and/or suggestions). ;-P"
so like. if you have thoughts, opinions, a vibe check, a hot take β send it. he literally wants it. the ;-P is doing so much work there and we love that for him π«Ά
πΈ COPYRIGHT πΈ
This program is free software; you can redistribute it and/or modify it under the same terms as Perl itself.
translation bestie: it's free, it's open, take it, remix it, ship it β just keep it under the same Perl-ish terms. no cap. π
and that's the whole page, gorgeous. this module/class was created for XML::Smart β that's its origin story, that's the lore π
this was written by Graciliano M. P. <gm@virtuasites.com.br>, documented under perl v5.36.0 on 2022-10-13, and it lives at MultiType(3pm). go forth and typecast responsibly, bestie π§ββοΈβ¨
π¦ where this page comes from
- ubuntu noble: libobject-multitype-perl 0.05-6 Β· Artistic-1.0-Perl OR GPL-1.0-or-later
- ubuntu resolute: libobject-multitype-perl 0.05-6 Β· Artistic-1.0-Perl OR GPL-1.0-or-later
- ubuntu stonking: libobject-multitype-perl 0.05-6 Β· Artistic-1.0-Perl OR GPL-1.0-or-later
- π girlified by deepseek-ai/DeepSeek-V4.1-Flash on : a language model's rewrite of the original, under its terms