NAME

    Object::Pad::Keyword::Accessor - declare lvalue accessors on
    Object::Pad classes

SYNOPSIS

       use Object::Pad;
       use Object::Pad::Keyword::Accessor;
    
       class Counter {
          use Carp;
    
          field $count = 0;
    
          accessor count {
             get { return $count }
             set ($new) {
                $new =~ m/^\d+$/ or croak "Invalid new value for count";
    
                $count = $new;
    
                say "Count has been updated to $count";
             }
          }
       }
    
       my $c = Counter->new;
       $c->count = 20;
    
       $c->count = "hello";  # is not permitted

DESCRIPTION

    This module provides a new keyword for declaring accessor methods that
    behave as lvalues as members of Object::Pad-based classes.

    While Object::Pad does permit fields of classes to be exposed to
    callers via lvalue mutator methods by using the :mutator field
    attribute, these are generally not that useful in real cases. Fields
    exposed using this technique have no validation, and cannot trigger any
    other code to be executed after update.

    The "accessor" keyword provided by this module offers an alternative.
    The lvalue accessor methods it provides into the class fully support
    running arbitrary code on read and write access, permitting any kind of
    check or triggering action. In fact, the accessor does not even need to
    be directly backed by a field at all. The accessor permits the class to
    specify its interface by which other code will interact with it,
    without being forced into any particular implementation of that
    interface.

    This module is a very early proof-of-concept, both of the syntax itself
    and the underlying ability of Object::Pad to support such syntax
    extensions as a third-party module.

 Motivation

    At first glance it may not seem immediately obvious why you would want
    to do this. After all, these accessors do not permit any new behaviours
    that couldn't be performed with a more traditional pair of get_* +
    set_* methods.

    The first reason is simply the declaration of intent on behalf of the
    class. Given a similarly-named get/set pair of methods, a user could
    guess that they probably behave like an accessor. But by providing the
    behaviour as a real accessor this makes a much firmer statement; where
    the user can much more strongly expect things like multiple read
    accesses to be idempotent and yield the same value as the most recent
    write access.

    The second reason is that perl already provides quite a number of
    mutating operators that allow a value to be edited in-place. These
    would not work at all with a get/set method pair, whereas they work
    just fine with these accessors. For example, given the code in the
    synopsis, the counter could be incremented simply by

       $c->count++;

    Whereas, if an lvalue accessor did not exist you would have to write
    this as something like

       $c->set_count( $c->count + 1 );

    The earlier form is much simpler, shorter, and much more obvious at
    first glance what it's doing. You don't, for example, have to check
    that the get and set method pair are indeed operating on the same
    thing. There's just one accessor of one object.

KEYWORDS

 accessor

       accessor NAME { PARTS... }

    Declares a new accessor method of the given name into the class. This
    will appear as a regular method, much as if declared by code such as

       method NAME :lvalue { ... }

    The behaviour of the accessor will be controlled by the parts given in
    the braces following its name. Note that these braces are not simply a
    code block; it does not accept arbitrary perl code. Only the following
    keywords may be used there.

  get

       accessor NAME { get { CODE... } }

    Provides a body of code to be invoked when a caller is attempting to
    read the value of the accessor. The code block behaves as a method,
    having access to the $self lexical as well as any fields already
    defined on the class. The value it returns will be the value passed
    back to the caller who read the accessor.

  set

       accessor NAME { set { CODE... } }
    
       accessor NAME { set ($var) { CODE... } }

    Provides a body of code to be invoked when a caller is attempting to
    write a new value for the accessor. The code block behaves like a
    method, having access to the $self lexical as well as any fields
    already defined on the class. The new value written by the caller will
    appear as the first positional argument to the method, accessible by
    code such as shift or $_[0].

    A second more succinct form allows the block to be written with a
    prefixed declaration of a variable name, using the same syntax as a
    subroutine signature (though this is not implemented by the same
    mechanism; it works on perl versions older than signatures are
    supported, and does not allow a defaulting expression or other syntax).

    If the code in this block throws an exception, that will propagate up
    to the caller who attempted to write the value. If this happens before
    the code block has stored the new value somewhere as a side-effect,
    then this will have the appearance of denying the modification at all.
    This is the way in which a validation check can be implemented.

    Similarly, the code is free to perform any other activity after it has
    stored the new value. This is is the way that post-update code
    triggering can be implemented. For example, if the object represents
    some sort of UI display widget it might decide to redraw the screen to
    reflect the updated value of whatever field just changed.

TODO

      * Some syntax to allow a field to be associated with the accessor, so
      it can automatically generate the get code, and assist the set code.
      This would permit an alternative form where code blocks for value
      validation check and post-update trigger were specified instead.

      Perhaps:

         field $x;
      
         accessor x {
            field($x)
            check ($new) { $new >= 0 or croak "Must be non-negative"; }
            trigger { $self->updated; }
         }

      * Integration with the constructor to permit a named-parameter at
      construction time that would automatically set the value of the
      accessor, as if the user had done so manually.

      Perhaps:

         accessor x :param { ... }

      * Consider whether to permit the accessor method itself to take
      arguments, allowing for some kind of indexed or parametric accessor.

      Perhaps:

         field @palette;
      
         accessor colour($index) {
            get { return $palette[$index]; }
            set ($new) { $palette[$index] = $new; }
         }

AUTHOR

    Paul Evans <leonerd@leonerd.org.uk>

