- DECLARING SLOTS
- COMPILATION PHASES
- COPYRIGHT AND LICENSE
Class::Slot - Simple, efficient, comple-time class declaration
package Point; use Class::Slot; use Types::Standard -types; slot x => Int, rw => 1, req => 1; slot y => Int, rw => 1, req => 1; slot z => Int, rw => 1, def => 0; 1; my $p = Point->new(x => 10, y => 20); $p->x(30); # x is set to 30 $p->y; # 20 $p->z; # 0
Similar to the fields pragma,
slot declares individual fields in a class, building a constructor and slot accessor methods.
Although not nearly as full-featured as other solutions,
Class::Slot is light-weight, fast, works with basic Perl objects, and imposes no dependencies outside of the Perl core distribution. Currently, only the unit tests require non-core packages.
Class::Slot is intended for use with Perl's bare metal objects. It provides a simple mechanism for building accessor and constructor code at compile time.
It does not provide inheritance; that is done by setting
@ISA or via the
It does not provide method wrappers; that is done with the
It does build a constructor method,
new, with support for default and required slots as keyword arguments and type validation of caller-supplied values.
It does build accesor methods (reader or combined reader/writer, using the slot's name) for each slot declared, with support for type validation.
@SLOTS package variable is added to the declaring package and is a list of quoted slot identifiers.
@SLOTS includes all slots available to this class, including those defined in its ancestors.
Class::Slot generates a constructor method named
new. If there is already an existing method with that name, it may be overwritten, depending on the order of execution.
The pragma itself accepts two positional parameters: the slot name and optional type. The type is validated during construction and in the setter, if the slot is read-write.
Slot names must be valid perl identifiers suitable for subroutine names. Types must be either a code ref which returns true for valid values or an instance of a class that supports the
check methods (see "Inlining methods" in Type::Tiny).
slot pragma may be used as either a keyword or a pragma. The following are equivalent:
use Class::Slot x => Int; use slot x => Int; slot x => Int;
A simple source filter is used to translate uses of
use slot into
When true, the accessor method accepts a single parameter to modify the slot value. If the slot declares a type, the accessor will croak if the new value does not validate.
When true, this constructor will croak if the slot is missing from the named parameters passed to the constructor. If the slot also declares a default value, this attribute is moot.
When present, this value or code ref which returns a value is used as the default if the slot is missing from the named parameters passed to the constructor.
If the default is a code ref which generates a value and a type is specified, note that the code ref will be called during compilation to validate its type rather than re-validating it with every accessor call.
When a class declares a slot which is also declared in the parent class, the parent class' settings are overridden. Any options not included in the overriding class' slot declaration remain in effect in the child class.
package A; use Class::Slot; slot 'foo', rw => 1; slot 'bar', req => 1, rw => 1; 1; package B; use Class::Slot; use parent -norequire, 'A'; slot 'foo', req => 1; # B->foo is req, inherits rw slot 'bar', rw => 0; # B->bar inherits req, but is no longer rw 1;
slot statements are evaluated by the perl interpreter at the earliest possible moment. At this time,
Class::Slot is still gathering slot declarations and the class is not fully assembled.
All slots are assumed to be declared by the
CHECK phase. The first slot declaration adds a
CHECK block to the package that installs all generated accessor methods in the declaring class. This may additionally trigger any parent classes (identified by
@ISA) which are not yet complete.
CHECK is not available (for example, because the class was generated in a string eval), the generated code will be evaluated at run-time the first time the class'
new method is called.
use Class::Slot -debug to your class will cause
Class::Slot to print the generated constructor and accessor code just before it is evaluated.
use Class::Slot -debugall anywhere will cause
Class::Slot to emit debug messages globally.
These may be set from the shell with the
CLASS_SLOT_DEBUG environmental variable.
Class::Slot is designed to be fast and have a low overhead. When available, Class::XSAccessor is used to generate the class accessors. This applies to slots that are not writable or are writable but have no declared type.
This behavior can be disabled by setting
$Class::Slot::XS to a negative value, although this must be done in a
BEGIN block before declaring any slots, or by setting the environmental variable
CLASS_SLOT_NO_XS to a positive value before running.
A minimal benchmark on my admittedly underpowered system compares Moose, Moo, and Class::Slot. The test includes multiple setters using a mix of inherited, typed and untyped, attributes, which ammortizes the benefit of Class::XSAccessor to Moo and Class::Slot.
| Rate moo moose slot | moo 355872/s -- -51% -63% | moose 719424/s 102% -- -25% | slot 961538/s 170% 34% --
| Rate moo moose slot | moo 377358/s -- -50% -56% | moose 757576/s 101% -- -12% | slot 862069/s 128% 14% --
Jeff Ober <email@example.com>
This software is copyright (c) 2018 by Jeff Ober.
This is free software; you can redistribute it and/or modify it under the same terms as the Perl 5 programming language system itself.