RFC 90 (v3) Arrays: Builtins: merge() and demerge()

[email protected] (Perl6 RFC Librarian)
Newsgroups perl.perl6.announce.rfc,perl.perl6.language.data
Message-ID <[email protected]>
This and other RFCs are available on the web at
  http://dev.perl.org/rfc/

=head1 TITLE

Arrays: Builtins: merge() and demerge()

=head1 VERSION

  Maintainer: Jeremy Howard <[email protected]>
  Date: 10 August 2000
  Last Modified: 8 September 2000
  Mailing List: [email protected]
  Number: 90
  Version: 3
  Status: Developing

=head1 ABSTRACT

It is proposed that two new functions, C<merge>, and C<demerge>, be added
to Perl. C<merge(@list1, @list2, ...)> would return a list that
interleaved its arguments. C<demerge($num_lists, @list)> would reverse
this operation. Both functions would return an alias into the original
list, not a copy of the elements.

=head1 CHANGES

=head2 Since v2

=over 4

=item *

Described aliasing behaviour of C<merge> and <demerge>

=head2 Since v1

=over 4

=item *

Moved list to [email protected]

=item *

Changed name from zip/unzip

=item *

Pass lists directly in examples, not references

=item *

Change 2nd argument from $list_size to $num_lists

=back

=head1 DESCRIPTION

It is proposed that Perl implement a function called C<merge> that
interleaves the arguments of arrays together, and is evaluated lazily.
For instance:

  @a = (1,3,5);
  @b = (2,4,6);
  @merged_list = merge(@a,@b);   # (1,2,3,4,5,6)

This makes it easy to operate on multiple lists using flexible reduction
functions:

  $sum_xy = sub {reduce ^last+^x*^y, merge($_[0], $_[1])};
  print $sum_xy->(@a, @b);   # Prints '44', i.e. 1*2+3*4+5*6

In order to reverse this operation we need an C<demerge> function:

  @merged_list = merge(@a,@b);   # (1,2,3,4,5,6)
  @demerged_list = demerge(2, @merged_list);   # ([1,3,5], [2,4,6])

The second argument to C<demerge> is the number of lists that are to be
created (i.e. the number of lists that would have been C<merge>d for this
to reverse the operation).

If the list to be demerged is not an exact multiple of the partition size,
the final list references are not padded--their length is one less than
the list size. For example:

  @list = (1..7);
  @demerged_list2 = demerge(3, @list);   # ([1,4,7], [2,5], [3,6])

Both C<merge> and <demerge> do not make a copy of the elements of their
arguments; they simply create an alias to them:

  @a = (1,3,5);
  @b = (2,4,6);
  @merged_list = merge(@a,@b);   # (1,2,3,4,5,6)
  $merged_list[1] = 0;
  @b == (0,4,6);                 # True
    
=head1 IMPLEMENTATION

The C<merge> and C<demerge> functions should be evaluated lazily.

C<merge> and C<demerge> return an alias into the original list, not a copy
of the elements.

Effectively, C<merge> creates an iterator over multiple lists. If used as
part of a reduction, the actual interleaved list need never be created.
For instance:

  $sum_xy = sub {reduce ^last+^x*^y, merge($_[0], $_[1])};
  $answer = $sum_xy->(@a, @b);
  
should be evaluated as if it read:

  $answer = 0;
  $answer += $a[$_] * $b[$_] for (0..$#a-1));
  
which does not need to create an intermediate list.

=head1 REFERENCES

RFC 23: Higher order functions

RFC 76: Builtin: reduce

RFC 91: Builtin: partition
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.