http://www.perlmonks.org?node_id=219972

This was originially a response to Re^2: lvalue considered harmful..., but in writing it, a bigger question arose.

Does anyone use lvalue subs? If so, for what?

I realise that the these were added as and remain an experimental feature, but they must have been added for a reason. I'm just wondering what the reason was. As they are, the only thing that can be done with the assigned value is ... well, to assign it to something. Sure, you can decide what to assign it to using the values past via the normal @_ mechanism to make the determination, but there is absolutely no way to inspect the value of the assign value either before you assign it nor after is was assigned. That means it is impossible to perform any verification on the assigned value. This may work for things like substr and splice, that simply don't care what is assigned, but it makes using lvaue subs for any other purpose pretty much useless. I note that vec can and does inspect the value assigned in that it will reject non-numerical assignments as it has to process them in order to use them. This is exactly the facility I would like to use.

To me, this makes the utility of :lvalue pretty much non-existant. Which is a shame, because I think that the semantics of lvalue subs has a lot going for it.

I don't see any reason why the assigned value shouldn't be made available to the sub through any one of a number of mechanisms:

  • Prepended or appended to the @_ array with unshift or push much as is currently done with $self in methods.

    I can see how this could break existing code though.

  • Made available to the sub under the same name as the sub itself as is done in some languages.

    Without thinking about it very hard, localising the typeglob for the subs name could be used as the mechanism for this, but as I am not familiar with Perl internals, this might not be as simple as it is apparently obvious (to me).

  • Aliasing the assigned value using $_, localised for the duration of the sub seems a fairly perlish idea to me.

    If this was only done for lvalue subs, I cannot see it breaking any existing code. However, this would restrict assignment to a single value which doesn't seem so perlish, but (from my experimentation so far) appears to be a restriction with the current implementation for user defined subs.

    my @test; sub test{ @test }; test() = (1..10); my @array = test() = (1..10);

    both give the error msg "Can't return array to lvalue scalar context", which suggests that the second line ought to work, but doesn't recognise the context correctly?

    There is a precedent for assigning a list to an lvalue sub namely splice, but I've failed to get it to work for my own subs.

  • Utilising one of the currently unused $^x vars similar to $^N for the extended regex (?{}) construct.

    A quick scan of perlop suggests that as of perl v5.6.1, that the following $^x vars are unused: BGJKNQUYZ.

    Though perhaps the most obvious (and vaguely mnemonic: Like $_, but different :^) would be $^_ which is available and assignable.

    This could be extended to be @^_ if list assignment were/is possible

Of these mechanisms, I like the alising of the subs name the best I think. It seems a fairly natural mechanism that $subname[0] would alias the (first) value assigned to an lvalue sub and @subname would alias the list of values assigned to the an lvalue sub. It has the virtue of not clashing with any existing mechanism as far as I can see. It has the possible downside that as a new mechanism it might be hard to implement?

Using @^_ and/or $^_ would be my second choice.

I would be interested to hear about anyones experience of using the current implementation of lvalue subs successfully, as well as comments on my thoughts for extending it. Also, if anyone thinks or knows if this would be likely to be accepted as a patch for a perl 5 ( I assume something better will be in place for perl 6), and any thoughts on how hard that would be to do.

BrowserUk.


Examine what is said, not who speaks.


update (broquaint): added <readmore> tags

Replies are listed 'Best First'.
Re: What the [sub]in 'L value do they have?
by Chmrr (Vicar) on Dec 15, 2002 at 08:37 UTC

    The only time I used : lvalue was in writing the following subroutine:

    sub set : lvalue { @_ == 1 ? $_[0] : set($_[0]{$_[1]},@_[2..$#_]); }

    ..which is used to set values at any depth in a recursive hash structure, like so:

    use Data::Dumper; sub set : lvalue { @_ == 1 ? $_[0] : set($_[0]{$_[1]},@_[2..$#_]); } my $h = {foo => 1, bar => 2, baz => { troz => 3, zort => 4, poit => { qux => 5, quux => 6, }, }, }; print Dumper($h); set($h, qw/baz troz/) = 42; set($h, qw/baz poit qux/) = 17; print Dumper($h);

    In this particular case, doing data verification wasn't overly useful, but I can definately see when it might be. While I'm not convinced that using $_ "won't break any existing code," it seems to be the most perlish choice to use.

    perl -pe '"I lo*`+$^X$\"$]!$/"=~m%(.*)%s;$_=$1;y^`+*^e v^#$&V"+@( NO CARRIER'

Re: What the [sub]in 'L value do they have?
by adrianh (Chancellor) on Dec 15, 2002 at 12:01 UTC

    Since I wrote "lvalue considered harmful..." you can probably guess how much I use them :-)

    My ideal would be to be able to separate setting & getting into separate subs like in Pop-11 so you could do:

    sub foo { my $self = shift; $self->{foo}; }; sub :updater foo { my ($self, $val) = @_; $self->{foo} = $val; }; print "foo is ", $self->foo, "\n"; $self->foo = 42;

    Having this sort of structure keeps the getting and setting logic nice and clear, and (in an ideal world) you would be able to override the setter/getter subroutines separately in subclasses.

    Probably a complete sod to implement tho' :-)

Re: What the [sub]in 'L value do they have?
by Zaxo (Archbishop) on Dec 15, 2002 at 20:41 UTC

    I mainly agree with the objections to lvalue subs as an OO mechanism. They impose a syntax which exposes the implementation, and they allow direct accesss to data to be exported. As you say, constraint checking is not possible.

    The lvalue attribute means that the represented value is modifiable, not just assignable. Consider the following:

    { my $foo = 'boo' . $/; sub foo () : lvalue { $foo } } chomp foo; foo =~ s/o/r/; print foo;
    What will your visible future foo be in these cases? Your proposals all seem to require that the lvalue sub know a lot about the operators that bind it. It appears that that will produce a very heavy and baroque kind of attribute.

    I think that the lvalue attribute should be retained as the overloading mechanism that it is, and its use for exporting data recognized for its own properties. The fact that it is unsuitable for strict OO does not make it useless or harmful.

    After Compline,
    Zaxo

      Given the way :lvalue works now, I came to the same conclusion, but then I set about trying to understand what uses it did have, procedural code or otherwise and I came up empty. For a good, practical use anyway, but the documentation is sparse to put it mildy, which is why I decided to move my questions and thoughts away from the original thread.

      The fact that I can modify the original entity directly through an lvalue sub may be an optimisation, but I don't see substr($foo, 3, 2) = 'fred'; as intrinsically different from substr($foo, 3, 2, 'fred'); I had never thought of doing nor encountered anything that did:

      $s = "the quick brown fox"; substr($s, 4, 5) =~ s/ick/iet/; print $s; the quiet brown fox

      And that does have some interesting possibilities and is exactly the sort answer I was looking for. I'd like to see a real use for it and the benefits thereof described, but in the absence, you've given me a new way to look at a facility of perl that I long been intrigued by but have singularly failed to find a good use for.

      That said, I still like the syntactic possibility of lvalue assignment for mutators and the only thing stopping that is the exposure of information that the compiler/interpreter has available to it. As I can see at least two ways of making that information available that would not affect its current usage in anyway, and would not break any existing code, I wonder if this would be such a hard thing to do and what objections there could be to doing it?

      Like many features of perl, noone would be forced to use it, but it would give those that would like to (Ie. ME:^) another way to do things.


      Examine what is said, not who speaks.

Re: What the [sub]in 'L value do they have?
by Aristotle (Chancellor) on Dec 15, 2002 at 14:13 UTC
    Thumbs down to $subname[0]. What happens if I change sub foo to sub bar? I have to edit all of the instances in the function.

    Makeshifts last the longest.

      Erm. Thats 3 keystrokes + the new name in my editor?


      Examine what is said, not who speaks.