Hash::AsObject(3pm)
π Hash::AsObject π
okay bestie, so this is the manual page for Hash::AsObject(3pm), and honestly? it's giving "treat hashes as objects, with arbitrary accessors/mutators". that's literally the whole name. let's get into it π«Ά
β¨ SYNOPSIS β¨
$h = Hash::AsObject->new;
$h->foo(123);
print $h->foo; # prints 123
print $h->{'foo'}; # prints 123
$h->{'bar'}{'baz'} = 456;
print $h->bar->baz; # prints 456
look at that. immaculate. no notes π
πΈ DESCRIPTION πΈ
so a Hash::AsObject is a blessed hash that gives you read-write access to its elements using accessors. and yes, technically they're both accessors and mutators β they get AND they set, they do both, they're versatile like that. π
the whole design goal is that it acts as much like a plain hash as possible. which means, for example, you can use methods like DESTROY to get or set hash elements with that name. wild, right? more on that below, keep reading, don't skip β¨
π METHODS π
the entire point of this module is to hand you arbitrary methods. for the most part, those get defined at runtime by a specially written AUTOLOAD function. it's giving magic. it's giving main character β¨
but to behave properly in all cases, a bunch of special methods and functions have to be supported. some of them are actually defined, and some are just emulated inside AUTOLOAD. let's go one by one π¦
new
$h = Hash::AsObject->new;
$h = Hash::AsObject->new(\%some_hash);
$h = Hash::AsObject->new(%some_other_hash);
creates a new Hash::AsObject. iconic behavior, truly.
but here's the twist β if you call it as an instance method, it accesses a hash element 'new':
$h->{'new'} = 123;
$h->new; # 123
$h->new(456); # 456
so new is both the constructor AND a little element-accessor gremlin depending on how you call it. obsessed. π
isa
this method cannot be used to access a hash element 'isa', because Hash::AsObject doesn't attempt to handle it specially. so no, you can't use it to poke at an 'isa' key. it's taken. π
can
same energy, same deal: this can't be used to access a hash element 'can'. also taken. also not special-cased. π
AUTOLOAD
$h->{'AUTOLOAD'} = 'abc';
$h->AUTOLOAD; # 'abc'
$h->AUTOLOAD('xyz') # 'xyz'
Hash::AsObject::AUTOLOAD recognizes when AUTOLOAD is being called as an instance method, and treats that as an attempt to get or set the 'AUTOLOAD' hash element. it knows what it's doing, trust π«Ά
DESTROY
$h->{'DESTROY'} = [];
$h->DESTROY; # []
$h->DESTROY({}) # {}
DESTROY is called automatically by the Perl runtime when an object goes out of scope. and a Hash::AsObject can't distinguish that automatic call from a call that's just trying to access the element $h->{'DESTROY'} β so it blithely gets (or sets) the hash's 'DESTROY' element. and honestly? not a problem! because the Perl interpreter discards any value that DESTROY returns when it's called automatically. so the chaos is contained. slay π
VERSION
when called as a class method, this returns $Hash::AsObject::VERSION. when called as an instance method, it gets or sets the hash element 'VERSION'. two moods, one method β¨
import
since Hash::AsObject doesn't export any symbols, this method has no special significance β you can safely call it as a method to get or set an 'import' element.
and when called as a class method, nothing happens. just vibes. nothing. π
okay so quick recap on the special ones: can() and isa() are special because they're defined in the UNIVERSAL class that all packages automatically inherit from. unfortunately, this means you can't use Hash::AsObject to access elements 'can' and 'isa'. that's just how it is, bestie. π
π CAVEATS π
no distinction is made between non-existent elements and those that are present but undefined. nope. they're the same to this module. also, there's no way to delete an element without resorting to:
delete $h->{'foo'}
that's the only way out. periodt. π
storing a hash directly into an element of a Hash::AsObject instance has the effect of blessing that hash into Hash::AsObject. yes, really. it just does that. π³
for example, this code:
my $h = Hash::AsObject->new;
my $foo = { 'bar' => 1, 'baz' => 2 };
print ref($foo), "\n";
$h->foo($foo);
print ref($foo), "\n";
produces this output:
HASH
Hash::AsObject
see? the ref changed. the hash got blessed. it's a whole transformation arc π
the author says he could fix this, but then code like this would throw an exception, because $h->foo($foo) will return a plain hash reference, not an object:
$h->foo($foo)->bar;
okay, so he could make $h->foo($foo)->bar work, but then code like this wouldn't have the desired effect:
my $foo = { 'bar' => 123 };
$h->foo($foo);
$h->foo->bar(456);
print $foo->{'bar'}; # prints 123
print $h->foo->bar; # prints 456
and yeah, he supposes he could fix that too, but that's an awful lot of work for little apparent benefit. understandable honestly. let him know if you have any thoughts on this. π¬
π BUGS π
- autovivification is probably not emulated correctly. probably. π
- the blessing of hashes stored in a
Hash::AsObjectmight be considered a bug. or a feature. it depends on your point of view. truly a matter of perspective β¨
π¦ TO DO π¦
- add the capability to delete elements, perhaps like this:
use Hash::AsObject 'deleter' => 'kill';
$h = Hash::AsObject->new({'one' => 1, 'two' => 2});
kill $h, 'one';
that might seem to violate the prohibition against exporting functions from object-oriented packages, but then technically it wouldn't be exporting it from anywhere since the function would be constructed by hand. alternatively, it could work like this:
use Hash::AsObject 'deleter' => 'kill';
$h = Hash::AsObject->new({'one' => 1, 'two' => 2});
$h->kill('one');
but, again β what if the hash contained an element named 'kill'? π¬ the drama. the tension.
- define multiple classes in
Hash/AsObject.pm? for example, there could be one package for read-only access to a hash, one for hashes that throw exceptions when accessors for non-existent keys are called, etc. but this is hard to do fully without (a) altering the underlying hash, or (b) defining methods besidesAUTOLOAD. hmmm... π€
β VERSION β
0.06
π AUTHOR π
Paul Hoffman <nkuitse AT cpan DOT org>
π CREDITS π
Andy Wardley for Template::Stash, which was the inspiration. writing template code like this:
[% foo.bar.baz(qux) %]
made the author yearn to write Perl code like this:
foo->bar->baz($qux);
and honestly? that's such a relatable origin story. the yearning was real. π₯
π COPYRIGHT π
Copyright 2003-2007 Paul M. Hoffman. All rights reserved.
This program is free software; you can redistribute it and modify it under the same terms as Perl itself.
and that's the whole page bestie!! this one's from perl v5.36.0, dated 2022-12-12, and it's the Hash::AsObject(3pm) page β go forth and bless some hashes, you've got this π«Άβ¨π
π¦ where this page comes from
- debian bookworm: libhash-asobject-perl 0.13-4 Β· Artistic-1.0-Perl OR GPL-1.0-or-later
- debian trixie: libhash-asobject-perl 0.13-4 Β· Artistic-1.0-Perl OR GPL-1.0-or-later
- ubuntu noble: libhash-asobject-perl 0.13-4 Β· Artistic-1.0-Perl OR GPL-1.0-or-later
- ubuntu resolute: libhash-asobject-perl 0.13-4 Β· Artistic-1.0-Perl OR GPL-1.0-or-later
- ubuntu stonking: libhash-asobject-perl 0.13-4 Β· 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