This and other RFCs are available on the web at
  http://dev.perl.org/rfc/

=head1 TITLE

Lvalue subroutines: implicit and explicit assignment

=head1 VERSION

   Maintainer: James Mastros <[EMAIL PROTECTED]>
   Date: 24 Aug 2000
   Version: 1
   Mailing List: [EMAIL PROTECTED]
   Number: 149
   Status: Developing

=head1 ABSTRACT

This RFC proposes two parallel methods for subroutines to be used as lvalues:
implicit and explicit assignment.  These methods are similar to the methods
proposed previously in RFCs 107 and 118.

=head1 DESCRIPTION

=head2 Implicit Assignment

This is very similar to the lvalue subs in perl5.6, and to the method
recommended in RFC 107.

It allows code such as

        package Object;
        sub foo(\%inner) : method {
                return %inner{foo};
        }

to be used as the lvalue in an assignment.  It also allows it in a mutator
context with single-evalutation, and allows it to be dynamically assigned
to.

This requires, however, that the return statement not return the value of
C<%inner{foo}>, which is, after all, just a value and therefore cannot be
assigned to, but rather a reference thereto.

Therefore, the definition of the return function must be changed such that
it is lazy.

Additionally, the definition of assignment must not normally evaluate a lazy
expression, but rather evaluate it to the point where its value would become
the value of a B<variable>, and then assign to that variable.  If the
expression cannot be evaluated to that point, (for example, C<$x+3>), then
it may be an error to assign to it.

(The may be is there because we might try solving the equation of the
assignment until one side becomes the value of a variable, and then assigning
the value to the variable such that it becomes true.  This is almost certainly
what is meant by the original expression.  However, this almost certainly isn't
worth the effort required.)

(This process could also be expressed in terms of automatic enreferencing and
dereferencing, but this way seems more perlish.)

Given the definition of C<Object::foo> above, the code C<$obj-E<gt>foo = 42;>
should result in this process:

=over 3

=item 1.

C<Object::foo> is called

        Object::foo($obj);

=item 2.

The arguments are processed in accordance with the parameter list of foo:

        %inner = %$obj;


=item 3.

C<Object::foo> runs

=item 4.

C<Object::foo> returns.

        $temp = lazy $inner{foo} # = $obj->{foo}

=item 5.

The assignment is preformed.

        $temp = 42

=item 6.

The lazy expression is partially evaluated.

        $temp =>
        $obj->{foo}

=item 7.

The (real) assignment is preformed.

        $obj->{foo} = 42;

=back

The context of the LHS is propagated from the RHS.  This implies that the
RHS is evaluated first.

A lvalue sub using implicit assignment may be local()ized or safe()d using
the normal methods.

=head2 Explicit Assignment

In this form of lvalue sub, the sub is passed both it's LHS arguments and
it's RHS value.

To indicate that the subrotuine may be called with explicit assignment, one
or more of the elements of its parameter list must be declared with a
:lvalue attribute.

The context of the RHS is determined by the declared calling convention of
the lvalue sub.  If and only if the lvalue sub is defined to take one scalar
argument (not including a forced-reference [?]), then the RHS is evaluated
in a scalar context.  Otherwise, it is evaluated in a list context.

If more explicit contexts are added, then the context of the RHS exactly
matches that specified by the C<:lvalue>d elements of the LHS' parameter
list.

Given the code

        sub mode(\%self; $mode :lvalue) {
         if ($mode <5 && $mode >= 0) {
          %self{mode} = $mode;
         } else {
          carp "Mode outside of range 0..5!";
         }
        }

The code C<mode($foo) = 3;> executes by calling mode with %self = %$foo and
$mode = 3.  The code C<mode($foo) = qw(3 4 5)> has the same effect, since
C<qw(3 4 5)> is it's lengh in scalar context.  The code C<mode($foo)>
executes by calling mode wih %self = %$foo and $mode undef (it would be an
error had the semicolon been a comma).

Note that the RHS is evaluated first, since it's context can be gathered
from
the signature of the lvalue sub.

Mutators are called with the lvalue part being the result of calling the
function first in a rvalue context lazaly.

Thus, the code C<mode($foo)++> results in a call to C<mode($foo, lazy
mode($foo)+1);>.  It is the lvalue sub's responsibility to make certain that
single-evaluation semantics are followed if it wishes to do so by decomposing
the lazy parameter.  Such decomposition is outside the realm of this RFC.

It is not possible to C<local()>ize or C<safe()>ty an explicit-assignment style
lvalue sub in a manner transparent to that sub.  For that reason, a closure
returning the current rvalue of the lvalue sub is created into a temporary.
The temporary is then evaluated and it's value assigned back to the call at
then end of the block (but only if the block exits cleanly in the case of a
safe() assignment).

Thus, given the definition of mode above,

        {
         local mode($foo) = 1;
         ...;
        }

Results in code equivalent to

        {
         my $temp = sub { mode($foo) }; #create a closure
         mode($foo) = 1;
         ...;
         mode($foo) = &$temp; #evaluate the closure
        }

Note that this results in three calls to the sub in response to one explicit
assignment.  This may be a very bad thing in some cases, but is unavoidable.

=head2 Miscellany

A subroutine may be marked as being in error to call in a lvalue context by
specifying a C<:nonlvalue> attribute on it.  This prevents it from being
called as an implicit lvalue function.

=head1 REFERENCES

RFC 118: lvalue subs: parameters, explicit assignment, and wantarray() changes:
        This is the basis for our explicit assignment section.

RFC 107: lvalue subs should receive the rvalue as an argument:
        This is the basis for our implicit assignment section.

RFC 132: subroutines should be able to return an lvalue:
        We, in effect, always make the value returned by C<return> a valid
        lvalue, so that the same code can be used for both the rvalue and
        lvalue cases.  This is in direct contradiction to the lreturn
        keyword recommended here.

RFC 130: Transaction-enabled variables for Perl6:
        We discuss how lvalue subs can be safe()d in the Implementation
        sections.

RFC 128: Subroutines: Extend subroutine contexts to include named
        parameters and lazy arguments:
        We use the syntax defined here.

L<perlfunc/return>: We extend the definition of return given here.



Reply via email to