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