Question

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

Was it helpful?

Solution

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 significantly 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.

OTHER TIPS

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.

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);

I can't speak for using them much in my normal Perl stuff, but they are used extensively in the Perl Data Language when taking slices or other subsections of a piddle. For example:

my $a = sequence(100);
# use lvalue in this increment:
$a->where($a < 10)++;

# Zero-out the last four elements
# notice the use of the overloaded .= operator:
$a->slice("-10:") .= 0;

Like many things in Perl, this feature is not used much across the whole ecosystem, but its use at least in this niche makes life much easier for users of PDL.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top