El siguiente ejemplo muestra una subrutina que
permite realizar la suma, el producto, etc. de un número
n
de vectores.
Para ello recibe
una referencia a una subrutina implantando una operación
binaria conmutativa y una lista de referencias a
listas (una matriz en la que las filas pueden ser de distinta
longitud). Por ejemplo, las siguientes llamadas son legales:
my @m = operate( \&plus, \@b, \@a); my @m2 = operate( \×, \@a, \@b, \@c);Donde las funciones
plus
y times
vienen definidas por:
sub plus { $_[0]+$_[1] } sub times { $_[0]*$_[1] }
La siguiente ejecución ilustra el modo de funcionamiento:
lhp@nereida:~/Lperl/src$ vect3.pl a = (3 2 1 9) b = (5 6 7) c = (1 2) a+b: 8 8 8 9 a*b*c: 15 24 7 9 max(a, b, c): 5 6 7 9
La rutina operate
devuelve un vector conteniendo el resultado
de operar vectorialmente los diferentes vectores.
Si un vector es mas corto que otro se supone que es extendido a la longitud del mas largo con elementos iguales al elemento neutro de la operación usada. La operación se supone conmutativa:
lhp@nereida:~/Lperl/src$ cat -n vect3.pl 1 #!/usr/bin/perl -w 2 use strict; 3 use List::Util qw(reduce max); 4 5 sub operate { 6 my $rop = shift; 7 die "Provide a subref\n" unless ref($rop) eq 'CODE'; 8 my @length = map { scalar(@$_) } @_; # lengths of the different lists 9 10 # index of longest list 11 our ($a, $b); 12 my $longest = reduce { $length[$a] < $length[$b]?$b:$a } 0..$#_; 13 my @res = @{splice @_, $longest, 1}; 14 15 for my $v (@_) { 16 my $i = 0; 17 @res[0..$#$v] = map { $rop->($_, $res[$i++]) } @$v; 18 } 19 return @res; 20 } 21 22 sub plus { $_[0]+$_[1] } 23 sub times { $_[0]*$_[1] } 24 25 my @a = (3, 2, 1, 9); print "a = (@a)\n"; 26 my @b = (5, 6, 7); print "b = (@b)\n"; 27 my @c = (1, 2); print "c = (@c)\n"; 28 my @m = operate( \&plus, \@b, \@a); 29 print "a+b:\n@m\n"; 30 my @m2 = operate( \×, \@a, \@b, \@c); 31 print "a*b*c:\n@m2\n"; 32 my @m3 = operate( \&max, \@a, \@b, \@c); 33 print "max(a, b, c):\n@m3\n";
La función reduce aplica el bloque de código a la lista. Inicialmente las
variables $a
y $b
contienen los dos primeros elementos. El bloque es llamado
y el resultado devuelto por el bloque queda en $a
. A continuación $b
recorre los elementos de la lista siendo operado con $a
y dejando siempre el resultado
en $a
. El valor final de $a
es el valor devuelto por reduce
.
Casiano Rodríguez León