accessors(3pm)

πŸ“¦
version 1.01 Β· 5 versions
, in ubuntu noble, ubuntu resolute, ubuntu stonking

✨ accessors ✨

okay bestie, so this is the accessors page from the User Contributed Perl Documentation (section 3pm, Perl modules, iykyk) πŸ’… and it's genuinely one of the cutest little pragmas out there. here's the whole thing, no skips, no cap.


πŸ’– NAME πŸ’–

accessors β€” create accessor methods in caller's package. that's it. that's the whole job. she's simple like that πŸŽ€


🌸 SYNOPSIS 🌸

package Foo;
use accessors qw( foo bar baz );

my $obj = bless {}, 'Foo';

# generates chaining accessors
# that you can set like this:
$obj->foo( 'hello ' )
    ->bar( 'world' )
    ->baz( "!\n" );

# you get the values by passing no params:
print $obj->foo, $obj->bar, $obj->baz;

look at that chain 😭 it's giving fluent API main character energy and you didn't even have to write a single sub yourself.


πŸ¦‹ DESCRIPTION πŸ¦‹

so the accessors pragma lets you create simple accessors at compile-time. not runtime, not "whenever you feel like it" β€” compile-time, periodt ✨

this saves you from writing them by hand, which lowkey always ends in cut-n-paste errors and a whole mess of duplicated code. it can also help you reduce the ammount of unwanted direct-variable access that creeps into your codebase when you're feeling lazy. (yes, that's the original's spelling of "ammount", we're keeping it exactly as-is bestie, no edits πŸ’œ)

and lowkey? accessors was designed with laziness in mind. the founder of this module understood the assignment πŸ™ˆ

method-chaining accessors are generated by default. but heads up: you can still use accessors::chained directly for reasons of backwards compatibility, if that's your vibe.

and if method chaining isn't your thing and you want accessors that always return the current value, go see accessors::classic. different flavor, same energy πŸ“


πŸ‘‘ GENERATED METHODS πŸ‘‘

accessors will generate methods that return the current object on set:

sub foo {
    my $self = shift;
    if (@_) { $self->{-foo} = shift; return $self; }
    else    { return $self->{-foo}; }
}

see how it returns $self when you're setting? that's the trick. this way they can be chained together and you get the whole $obj->foo(...)->bar(...)->baz(...) slay πŸ’…

πŸ’€ Why prepend the dash?

the dash (-) is prepended to the property name for a few reasons:

  • interoperability with Error.
  • to make it difficult to accidentally access the property directly, ala:
use accessors qw( foo );
$obj->{foo};  # prevents this by mistake
$obj->foo;    # when you probably meant this

(this might sound woolly, but it's easy enough to do).

  • syntactic sugar (this is woolly :).

bestie, you shouldn't care too much about how the property is stored anyway. if you do care, you're likely trying to do something special β€” and honestly you should really consider writing the accessors out long hand. or it's simply a matter of preference, in which case you can use accessors::classic, or sub-class this module. either way, options! 🌈


πŸ”₯ PERFORMANCE πŸ”₯

there is little-to-no performace hit when using generated accessors. in fact there is usually a performance gain. (again: that's the original's spelling of "performace", we do not touch the source text, we respect the source text 🫢)

  • typically 10-30% faster than hard-coded accessors (like the above example).
  • typically 1-15% slower than optimized accessors (less readable).
  • typically a small performance hit at startup (accessors are created at compile-time).
  • uses the same anonymous sub to reduce memory consumption (sometimes by 80%).

see the benchmark tests included with this distribution for more details β€” receipts exist, go look πŸ‘‘


🌟 MOTIVATION 🌟

the main difference between the accessors pragma and other accessor generators is simplicity.

  • interface

use accessors qw( ... ) is as easy as it gets. literally one line. that's the whole onboarding.

  • a pragma

it fits in nicely with the base pragma:

use base      qw( Some::Class );
use accessors qw( foo bar baz );

and accessors get created at compile-time. cute, tidy, done.

  • no bells and whistles

the module is extensible instead. minimal queen behavior πŸ’…


🧚 SUB-CLASSING 🧚

if you prefer a different style of accessor, or you need to do something more complicated, there's nothing to stop you from sub-classing. it should be pretty easy, fr fr.

look through accessors::classic, accessors::ro, and accessors::rw to see how it's done. go peek, take notes, steal the vibe πŸ“


πŸ’€ CAVEATS πŸ’€

classes using blessed scalarrefs, arrayrefs, etc. are not supported β€” for sake of simplicity. only hashrefs are supported.

that's the deal, bestie. no exceptions, no secret workaround listed here. hashrefs only. periodt.


πŸ™ THANKS πŸ™

thanks to Michael G. Schwern for indirectly inspiring this module, and for his feedback & suggestions. icon behavior.

also to Paul Makepeace and David Wright for showing me faster accessors, to chocolateboy for his contributions, to the CPAN Testers for their bug reports, and to James Duncan and people on London.pm for their feedback. y'all ate πŸ’–


πŸ’œ AUTHOR πŸ’œ

Steve Purkis <spurkis@cpan.org>


🌈 SEE ALSO 🌈

accessors::classic, accessors::chained

similar and related modules:

base, fields, Class::Accessor, Class::Struct, Class::Methodmaker, Class::Generate, Class::Class, Class::Tangram, Object::Tiny


aaaand that's the whole page bestie, every option, every default, every caveat, nothing skipped 🫢 this was perl v5.36.0, dated 2022-10-13, accessors(3pm) β€” go chain some accessors and slay πŸ’…βœ¨πŸŽ€

πŸ“¦ where this page comes from