develooper Front page | | Postings from August 2000

82 (v2): Apply operators component-wise in a list context

Casey R. Tweten
August 24, 2000 09:50
82 (v2): Apply operators component-wise in a list context
Message ID:
=head1 TITLE

Apply operators component-wise in a list context

=head1 VERSION

  Maintainer: Jeremy Howard <>
  Created: 10 August 2000
  Last modified: 16 August 2000
  Version: 2
  Mailing List:
  Number: 82


It is proposed that in a list context, operators are applied
component-wise to their arguments. Furthermore, it is proposed that
this behaviour be extended to functions that do not provide a specific
list context.

=head1 CHANGES

=head2 Since v1

=over 4

=item *

Added the ability to apply an operator to a scalar and a list.

=item *

Added more examples, including text processing examples.



Currently, operators applied to lists in a list context behave

  @b = (1,2,3);
  @c = (2,4,6);
  @d = @b * @c;   # Returns (9) == scalar @b * scalar @c

This RFC proposes that operators in a list context should be applied
component-wise to the elements of their arguments:

  @d = @b * @c;   # Returns (2,8,18)

If the lists are not of equal length, the shorter lists should be treated
as if they were padded with undefs at the right-hand end. However, this
implicit padding should not cause these elements in the shorter lists to

If an operator is used in a list context with one list, and one or more
scalars, the scalars are treated as if they were a list of that scalar:

  @b = (1,2,3);
  @e = @b * 2;      # Returns (2,4,6)
  @f = @b * (2,2,2) # Same thing

Functions that do not return a list should be treated in the same way:

  @e = (-1,1,-3);
  @f = abs(@e);   # Returns (1,1,3)


=head2 Text processing

If @first_names contains a list of peoples first names, and @surnames
contains their surnames, this creates a new list that concatenates the
elements of the two lists:

  @full_names = @first_names . @surnames;

To quote a number of lines of a message by prefixing them all with '> ':

  @quoted_lines = '> ' . @raw_lines;

To create a histogram for a list of scores:

  @people = ('adam', 'eve ', 'bob ');
  @scores = (7,9,5);          # Score for each person
  @histogram = '#' x @scores; # Returns ('xxxxxxx','xxxxxxxxx','xxxxx')
  print join("\n", @people . ' ' . @histogram);

  adam xxxxxxx
  eve  xxxxxxxxx
  bob  xxxxx

=head2 Number crunching

This snippet multiplies the absolute values of three arrays together and
sums the results, in a very efficient way:

  @b = (1,2,3);
  @c = (2,4,6);
  @d = (-2,-4,-6);
  $sum = reduce ^_+^_, abs(@b * @c + @d);

Lists can be reordered or sliced with list generation functions (RFC 81)
allowing flexible data manipulation:

  @a = (3,6,9);
  @reverse = (3..1);
  @b = @a * @a[@rev];   # (3*9, 6*6, 9*3) = (27,36,27)

Slicing plus array operations makes matrix algebra easy:

  @a = (1,2,3,
  @column1of3 = (1:3:7);   # (1,4,7) - every 3rd elem from 1 to 7
  @row1of3 = (1..3);       # (1,2,3)
  $sum_col1_by_row1 =
    sum ( @a[@column1of3] * @a[@row1of3] );  # (1*1+2*2+3*3)=14


These operators and functions should be evaluated lazily. For instance:

  @b = (1,2,3);
  @c = (2,4,6);
  @d = (-2,-4,-6);
  $sum = reduce ^_+^_, @b * @c + @d;

should be evaluated as if it read:

  $sum = 0;
  $sum += $b[$_] * $c[$_] + $d[_] for (0..$#a-1));

That is, no temporary list is created, and only one loop is required.

The proposal to handle functions is tricky, since there is currently no
obvious way to see whether a function is going to return a list. For
instance, in the case:

  @b = abs(@a);

we either need some kind of more advanced prototyping (or other way of
creating a signature) so that Perl knows to apply abs() to the elements of
@a, or we need to manually change abs to check for list context and Do The
Right Thing.


The Mathematica Navigator, Heikki Ruskeep,
Academic Press, ISBN 0-12-603640-3, p383.

Expression Templates (C++ Implementation):

Implementation in Perl Data Language:

RFC 76: reduce

RFC 23: Higher-order functions

RFC 81: Lazily evaluated list generation functions
print(join(' ', qw(Casey R. Tweten)));my $sig={mail=>'',site=>
''};print "\n",'.'x(length($sig->{site})+6),"\n";
print map{$_.': '.$sig->{$_}."\n"}sort{$sig->{$a}cmp$sig->{$b}}keys%{$sig};
my $VERSION = '0.01'; #'patched' by Jerrad Pierce <belg4mit at MIT dot EDU> Perl Programming lists via nntp and http.
Comments to Ask Bjørn Hansen at | Group listing | About