You could avoid some duplication by using the following syntax:
sub name { my $arg = ref $_[0] ? $_[0] : \do{my $anon = $_[0]}; # Do stuff. $$arg =~ s/^un//; return $$arg; }
or using an alias instead of a reference:
sub name { our $arg; local *arg = ref($_[0]) ? $_[0] : \do{my $anon = $_[0]}; # Do stuff. $arg =~ s/^un//; return $arg; }
Test code:
$i = $j = 'unchanged'; name(\$i); print("i:$i\n"); # i:changed $i = $j = 'unchanged'; $j = name($i); print("i:$i, j:$j\n"); # i:unchanged, j:changed $i = $j = 'unchanged'; $j = name(\$i); print("i:$i, j:$j\n"); # i:changed, j:changed
You could also check the calling context and avoid reference altogether:
sub name { our $arg; local *arg = defined wantarray ? \do{my $anon = $_[0]} : \$_[0]; # Do stuff. $arg =~ s/^un//; return $arg; }
but I'd avoid that since the it's not obvious what's going to happen when reading the call:
name($i); # In place $j = name($i); # Not in place sub test { name($_[0]) } # unknown!!! sub test { name($_[0]) } test($i); # In place sub test { name($_[0]) } $j = test($i); # Not in place
Update: Showed why wantarray is a bad idea instead of just saying it is.
Update: Fixed bug found by eff_i_g. That'll teach me to test without warnings.
Update: Oops, I forgot I should be able to read the argument, not just write to it. Fixed by changing \do{my ...} to \do{my ... = $_[0]}.
In reply to Re: Scalar and void subroutines
by ikegami
in thread Scalar and void subroutines
by eff_i_g
| For: | Use: | ||
| & | & | ||
| < | < | ||
| > | > | ||
| [ | [ | ||
| ] | ] |