Why? I suspect, you want to save typing and maybe gain readability - then use a sub.
Getting it done without a loop - explicit (foreach, while, etc.)
or implicit (map, grep, etc.)
is something you cannot get around - unless manually unrolling the loop, but that isn't flexible.
Three more ways to obscure, your're using a loop:
use strict;
use warnings;
use Scalar::Util qw(looks_like_number);
#-- Common helper
sub mul_if_num {
my ($expr, $factor) = @_;
return looks_like_number( $expr ) ? $factor * $expr : $expr;
}
#-- Cool1: Overloading
{
package ArrayMul;
use overload '*=' => \&mulby;
sub new {
my $self = shift;
return bless [ @_ ], __PACKAGE__;
}
sub mulby {
my ($self, $factor, $swap) = @_;
@$self = map{ main::mul_if_num( $_, $factor ) } @$self;
return $self;
}
1;
}
package main;
#-- Cool2: hide loop in sub - profit from re-use and readability
sub scalar_mul {
my ($aref, $factor) = @_;
#TODO: parameter checks (2 params, first is ref, second is scalar)
$_ = mul_if_num( $_, $factor ) for @{$aref};
die 'ill. context' if defined wantarray;
}
#-- Examples
my @array = qw(1 2 3 4 what? +1 -7 666+666);
my $array2 = ArrayMul->new( @array );
my @array3 = @array;
my @array4 = @array;
#-- Cool1! but no @-sigil. Unexpected side-effects likely.
$array2 *= 2;
#-- Cool2! loop hidden elsewhere
scalar_mul( \@array3, 3 );
#-- Cool3! but creates new array
use List::MoreUtils qw(apply);
@array4 = apply { $_ = mul_if_num( $_, 4 ) } @array;
#-- Results
print "@{$_}\n" for ( \@array, $array2 ,\@array3 , \@array4);
__END__
1 2 3 4 what? +1 -7 666+666
2 4 6 8 what? 2 -14 666+666
3 6 9 12 what? 3 -21 666+666
4 8 12 16 what? 4 -28 666+666
Personally, I would prefer the ... scalar_mul( \@array3, 3 ); ... variant.
|