Melly has asked for the wisdom of the Perl Monks concerning the following question:

Hi Monks

In the following script, why does the first attempt to lc @x fail, but the second works?

use strict; use warnings; my @x = qw(A B C); lc($_) for @x; # void warning print @x; # still UC print "\n"; s/(\w*)/lc($1)/e for @x; # why no void warning here? print @x; # LC - it worked
map{$a=1-$_/10;map{$d=$a;$e=$b=$_/20-2;map{($d,$e)=(2*$d*$e+$a,$e**2 -$d**2+$b);$c=$d**2+$e**2>4?$d=8:_}1..50;print$c}0..59;print$/}0..20
Tom Melly, pm (at) cursingmaggot (stop) co (stop) uk

Replies are listed 'Best First'.
Re: Changing arrays w/ and w/o regex
by Corion (Patriarch) on Nov 09, 2021 at 12:25 UTC

    lc is a function and in your first case, you are throwing away the result of the function. This is also why Perl warns you about throwing away the result of a function . "void context" means that you don't care about the result of a function, which is uncommon when calling a function.

    In the second case, you are using the result of the function, by using it in the replacement part of s///.

    When rewriting an array, it's common to use the map function to turn each element of the (old) array into a new value:

    @x = map { lc( $_ )} @x;

    I believe this can be written even shorter as

    @x = map lc, @x

    ... but that is overly short especially if you are not yet familiar with map.

    Updated: Added map as example

Re: Changing arrays w/ and w/o regex
by ikegami (Patriarch) on Nov 09, 2021 at 13:31 UTC

    You want

    $_ = lc for @x;
    or
    @x = map lc, @x;

    lc has no side effects. Its only effect is the value it returns. As such, it makes no sense to use it in void context, so it warns.

    s/// has the side effect of modifying the bound variable. The value it returns is but one of its effects. It not only makes sense to use it in void context, it's a common thing to do. It wouldn't make sense to warn.

    s///r has no side effects, so it too warns in void context.

    lc($_); # No effect. void warning $_ = lc($_); # Modifies $_. no warning s/.*/lc($_)/e; # Modifies $_. no warning s/.*/lc($_)/er; # No effect. void warning $_ = s/.*/lc($_)/er; # Modifies $_. no warning