[% setvar title Subroutines should be able to return an lvalue %]

This file is part of the Perl 6 Archive

Note: these documents may be out of date. Do not use as reference!

To see what is currently happening visit http://www.perl6.org/

TITLE

Subroutines should be able to return an lvalue

VERSION

  Maintainer: Johan Vromans <jvromans@squirrel.nl>
  Date: 18 Aug 2000
  Last Modified: 20 Sep 2000
  Mailing List: perl6-language-subs@perl.org
  Number: 132
  Version: 4
  Status: Frozen

NOTE

See CHANGES for wrap-up info.

ABSTRACT

RFC 107 proposes that lvalue subs should receive their rvalues as subroutine arguments. RFC 118 counter-proposes that lvalue subs should receive their rvalues as lexical variables named in a prototype associated with the :lvalue modifier. This RFC proposes a terrifying simple solution for the growing complexity of the lvalue subroutines problem. It proposes the keyword lreturn and discards the <:lvalue> property.

DESCRIPTION

If a sub wants to return an lvalue, this lvalue must be a real lvalue in all respects. In particular, all kinds of implicit and explicit value changes must be supported. For example,

    lvsub() = ...
    lvsub()++;
    lvsub() += ...
    lvsub() =~ s///
    for ( lvsub() ) {
        $_ = ...
    }
    sysread($fh,lvsub(),...)
    substr(lvsub(),...) = ...

and so on.

One often heard argument is that subroutines like these must be callable in either mode:

    lvsub(expr)
    lvsub() = expr

and that therefore "lvsub() = expr" is mere syntactic sugar for "lvsub(expr)". This argument is false, since the two uses are totally distinct. In the first case, the sub has control over what it does with the value while in the lvalue case the sub doesn't -- and doesn't care. If control is desired, use tie.

The clue is "If a sub wants to return an lvalue, what's returned must really be an lvalue". Therefore I propose a new keyword lreturn that behaves just like return, but returns the lvalue instead of the rvalue. After returning, everything is exactly as if the argument to lreturn were specified instead of the subroutine call. The <:lvalue> property is no longer needed and should be removed since it only causes confusion. A subroutine is not an lvalue thing, it returns an lvalue if it wants to.

For example:

    sub lvsub {
       ...
       lreturn $hash{somekey};
    }

    lvsub() =~ s///    # identical to $hash{somekey} =~ s///
    $ref = \lvsub()    # now $ref is \$hash{somekey}

As a thought guide: think of lreturn returning a reference to its argument, and the call to lvsub() performing a dereference.

With the enhanced want operator, subroutines can dynamically decide what to return.

Interesting note: you can always use lreturn instead of return; for rvalue cases it does not matter.

FUNDAMENTAL RESTRICTION

There aint no such thing as a free lunch, so there's a catch.

Good programming practice requires that, in assignments, the right hand side gets evaluated before the left hand side. This is to make statements like

    $a[$i++] = $b[$i++]

have a defined semantics. This principle enforces a restriction to subroutines that want to return an lvalue. Consider

    lvsub() = some_sub()

The problem is to determine the context in which some_sub() must be called. While with normal assignments this context is always clear, in this example the context is determined by what lvsub is going to lreturn, which is not going to happen before some_sub() has completed. The only solution seems to be to restrict lvalue subroutines to return only scalar lvalues.

Subroutine prototypes and/or attributes are often suggested as a means to overcome this restriction. However, due to the powers of Perl this is impossible. For example, consider sub foo that returns an array lvalue, and sub bar that returns a scalar lvalue. Even when prototyped or attributed, the following construction will cause problems:

    my $ref = $some_condition ? \&foo : \&bar;
    $ref->() = some_sub();

Another attempt to overcome this restriction is to change the evaluation order of assignments, probably only in case an lvalued sub is involved. I prefer not to consider this an option, but maybe others feel differently.

Therefore the restriction of lreturn to scalar lvalues must be considered a fundamental one. Fortunately, this restriction is not a problematic one. Scalars are already "more than common" in Perl. For example, arrays and hashes can only contain scalars, and nobody has ever considered that a problem. References rulez!

COMPATIBILITY

The proposed solution is upward compatible with the current Perl5 implementation of lvalued subroutines:

    sub foo : lvalue { ...; $var }

can be interpreted as a shorthand, or syntactic sugar, for

    sub foo { ...; lreturn $var }

IMPLEMENTATION

Every subroutine (and method) call can potentially return an lvalue, so the compiler cannot do smart things. All must be handled at run-time.

CHANGES

Version 4, 20 September 2000

Frozen after some discussions on the mailing list. People seem to be divided in two groups. One group considers an lvalue return solely for assignment, and hence propose to add an additional magical parameter to lvalue routines. Other RFCs deal with that approach. The other group joins me in the opinion that lvalue means, in essence, equivalence to a variable. This RFC is for them.

Version 4

Added CHANGES section.

Clarified the syntactic sugar misconception.

Version 3, Aug 28 2000

Add Status indicator.

REFERENCES

RFC 107: lvalue subs should receive the rvalue as an argument

RFC 118: lvalue subs: parameters, explicit assignment, and wantarray() changes

NRETURN, "The SNOBOL4 Programming Language", Griswold & Polonsky.

RFC 21: Replace wantarray with a generic want function