views:

576

answers:

3

I don't understand what could be the uses of lvalue subroutines? What is it that I can't accomplish with normal subroutines? Could you please post some examples?

Thanks

+4  A: 

They provide a different interface, that in some circumstances can be more intuitive. Unlike traditional setters, you can actually change the value directly. For example

lvalue_sub($foo) =~ s/foo/bar/;

can be cleaner than

my $tmp = some_sub($foo);
$tmp =~ s/foo/bar/;
some_sub($foo, $tmp);
Leon Timmermans
+7  A: 

LValues are recommended to be avoided. They're fun and all, but they confuse new users who make assumptions about how all subs work, and thus it should be avoided in code when a better way is available.

Sometimes it can be extremely practical to use an LValue result to do dirty work.

substr( $string, $start, $stop ) = 'somevalue' # replaces the specified part of the substring.

However, this also does the same thing:

substr( $string, $start, $stop , 'somevalue' );

The difference here being mostly the former has significant more expressive power, as it delegates the behaviour to the code that uses it instead of the function itself.

For instance:

substr( $string, $start, $stop ) =~ s/a/b/g

Would require you to do

my $x = substr( $string, $start, $stop ); 
$x =~ s/a/b/g/; 
substr( $string, $start, $stop, $x );

Which is a bit nasty.

Although, there's an additional nasty here, because you have to think about whether doing that substitution or not with $x works retroactively to modify the string or not ( due to substr being an LValue sub). I don't think it does, but Its ambiguous enough I have to check the manual to remember whether it does or not, and that's bad.

Kent Fredric
$x contains a copy, not an lvalue. But if you alias an lvalue substr ala `for (substr(...)) {` or `foo(substr(...))` you can do more than one thing with the lvalue.
ysth
+6  A: 

You can use lvalue subs as setters for object members:

sub x : lvalue {
    my $self = shift;
    $self->{x};
}

Then later:

$foo->x = 5;

This combines the intuitiveness of setting members directly with the flexibility of encapsulating the setter, in case you later want to change how the object is implemented. Compare to the following more traditional ways to set members in Perl:

Intuitive but fragile; what if you change how $foo is implemented?

$foo->{x} = 5;

Traditional setter method; doesn't use assignment syntax for what amounts to an assignment:

$foo->set_x(5);

Of course, lvalue methods have never really been embraced by the Perl community, and use of lvalue subs is "weird" and whatever would be gained for intuitiveness would be lost by the strangeness of it all.

nohat