Skip to content

Slot Attributes

Ovid edited this page Sep 14, 2021 · 14 revisions

Please see the main page of the repo for the actual RFC. As it states there:

Anything in the Wiki should be considered "rough drafts."

Click here to provide feedback.

Slots

Instance data for classes are in "slots." Slots are declare by: has $var;.

Note Other types such as has @var or has %var might come later. They're not in this proposal because it's unclear what has @var :reader :writer; means. Does it accept and return lists? It's also required in the constructor in that version. Does it then require an array reference? Due to the flattening nature of some variables in Perl, I'd rather punt on this for the time being.

The variable is the slot and only the slot. The has keyword does not create any readers, writers, have anything to with the constructors, and so on. It only declares the slot. It's the attributes which handle everything else.

has $x; is a private slot. Absent other attributes modifying it, it is:

  • Read-write (internally)
  • Forbidden in the constructor
  • Has no public reader or writer

has $x = $value; supplies a default value. See also :builder below.

Attributes

Attributes are for object construction and data modification, and helpers ("nice to haves" which make working with objects more pleasant).

Object Construction

Slots are defined via has $varname;. This does nothing outside of declaring the slot. Nothing at all. Instead, if we wish to specify arguments for the constructor, we use the :new syntax.

has $name :new;

If you wish the slot to be allowed to be passed in the constructor, but not required, you must provide default values, or a builder.

has $name :new = 'Ovid';

The default value, of course, may also be undef if you do not need a value for that slot.

The "name" of a slot is the identifier name of the slot variable. Thus, the name of has $person :new; is person. If you need it passed to the constructor with a different name, use the :name(...) attribute:

has $person :new :name(employee);

Absent a :new attribute, the attribute must not be passed to the constructor.

Helpers

Attribute Meaning Notes
:reader, :reader($name) Creates a read-only public method for the data N/A
:writer, :writer($name) Creates a public method (set_$name) for modifying the data This is frequently a code smell
:predicate, :predicate($name) Creates a has_$name boolean predicate What's the difference between uninitialized and undef?
:handles(@list|%kv_pairs) Delegates the methods to the object in this slot Requires an object!
:name($identifier) Public name of slot You cannot use :name on a multi-slot declaration

The writer creates a method called set_$name to avoid overloading the meaning of the method name, and will return the invocant. Setting :reader($name) and :writer($name) to the same $name would be an error. This is in part because Corinna would need to special case that and have to write more complicated internal code.

See Custom Writers for more explanation.

Data Modification

(Arguably, the :writer attribute could go here)

Attribute Meaning Notes
:builder, :builder($name) Creates a lazy builder for the slot. Conflicts: :new
:weak Weakens the variable in the slot N/A
:clearer Clears the slots. Sets it to undef if no default value Makes no sense without :reader?
:immediate Slot value is not lazy Only meaningful with a :builder

Valid Combinations

The above seems to simplify this work quite a bit. Assuming :writer to be a code smell, the following are "valid" combinations that are likely to be seen.

Note that all of these allow the `:name(identifier) attribute.

Declaration Constructor Attribute
has $x; No No
has $x :reader; No Yes
has $x :new; Yes No
has $x; No No
has $x :reader :clearer; No Yes
has $x :reader :new; Yes Yes
has $x :reader ; No Yes
has $x :builder ; No No
has $x = $default; No No
has $x :reader :new :clearer; Yes Yes
has $x :reader :clearer; No Yes
has $x :reader :builder ; No Yes
has $x :reader = $default; No Yes
has $x :builder :immediate; No No
has $x :immediate = $default; No No
has $x :reader :builder :clearer; No Yes
has $x :reader :builder :immediate; No Yes
has $x :reader :clearer = $default; No Yes
has $x :reader :immediate = $default; No Yes
has $x :reader :builder :immediate :clearer; No Yes
has $x :reader :immediate :clearer = $default; No Yes

Illegal:

We're working hard to ensure that you can't create an illegal set of attributes for a slot, but we still have a few).

  • :builder and = $default
  • :builder or = $default with :new
  • :immediate without :builder;
  • :clearer without :reader (do we really care about this?)
Clone this wiki locally