=head1 NAME Class::Slot - Simple, efficient, comple-time class declaration =head1 SYNOPSIS 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 =head1 DESCRIPTION Similar to the L pragma, C declares individual fields in a class, building a constructor and slot accessor methods. Although not nearly as full-featured as L L, C 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. C 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 I provide inheritance; that is done by setting C<@ISA> or via the C or C pragmas. It does I provide method wrappers; that is done with the C pseudo-class. It I build a constructor method, C, with support for default and required slots as keyword arguments and type validation of caller-supplied values. It I build accesor methods (reader or combined reader/writer, using the slot's name) for each slot declared, with support for type validation. =head1 @SLOTS The C<@SLOTS> package variable is added to the declaring package and is a list of quoted slot identifiers. C<@SLOTS> includes I slots available to this class, including those defined in its ancestors. =head1 CONSTRUCTOR C generates a constructor method named C. If there is already an existing method with that name, it may be overwritten, depending on the order of execution. =head1 DECLARING SLOTS 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 C, C, and C methods (see L). The C 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 C and C into C. =head1 OPTIONS =head2 rw 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. =head2 req 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 L value, this attribute is moot. =head2 def 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. =head1 INHERITANCE When a class declares a slot which is also declared in the parent class, the parent class' settings are overridden. Any options I 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; =head1 COMPILATION PHASES =head2 BEGIN C statements are evaluated by the perl interpreter at the earliest possible moment. At this time, C is still gathering slot declarations and the class is not fully assembled. =head2 CHECK All slots are assumed to be declared by the C phase. The first slot declaration adds a C block to the package that installs all generated accessor methods in the declaring class. This may additionally trigger any parent classes (identified by C<@ISA>) which are not yet complete. =head2 RUNTIME If C 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' C method is called. =head1 DEBUGGING Adding C to your class will cause C to print the generated constructor and accessor code just before it is evaluated. Adding C anywhere will cause C to emit debug messages globally. These may be set from the shell with the C environmental variable. =head1 PERFORMANCE C is designed to be fast and have a low overhead. When available, L 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 C<$Class::Slot::XS> to a negative value, although this must be done in a C block before declaring any slots, or by setting the environmental variable C to a positive value before running. A minimal benchmark on my admittedly underpowered system compares L, L, and L. The test includes multiple setters using a mix of inherited, typed and untyped, attributes, which ammortizes the benefit of Class::XSAccessor to L and L. | Rate moo moose slot | moo 355872/s -- -51% -63% | moose 719424/s 102% -- -25% | slot 961538/s 170% 34% -- Oddly, L seemed to perform better running the same test without L installed. | Rate moo moose slot | moo 377358/s -- -50% -56% | moose 757576/s 101% -- -12% | slot 862069/s 128% 14% -- =head1 AUTHOR Jeff Ober =head1 COPYRIGHT AND LICENSE 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.