[% setvar title Arrays: transpose() %]

This file is part of the Perl 6 Archive

Note: these documents may be out of date. Do not use as reference!

To see what is currently happening visit http://www.perl6.org/


Arrays: transpose()


  Maintainer: Jeremy Howard <j@howard.fm>
  Date: 22 Sep 2000
  Last Modified: 24 Sep 2000
  Mailing List: perl6-language-data@perl.org
  Number: 272
  Version: 2
  Status: Frozen


This RFC was modified to incorporate the functionality of PDL's xchg() and mv(), which are useful for acting on arbitrary dimensions of multidimensional arrays. Implementing aliasing was discussed in more detail than for RFCs 90, 91, and 148, including suggestions to learn from PDL's implementation (outlined in RFC 116), which are more sophisticated than simply keeping a list of mapped indices, instead actually storing information about the specific operations that have occured.


It is proposed that a new function transpose be added to Perl. transpose($dim1, $dim2, @list) would return @list with $dim1 and $dim2 switched. transpose(\@order, @list) would return @list with dimensions in the order specified by @order. transpose would return an alias into the original list, not a copy of the elements.


Swapping Dimensions

It is proposed that Perl implement a function called transpose that transposes two dimensions of an array, and is evaluated lazily. "RFC 202" gives an overview of the proposed multidimensional arrays that transpose works with. For instance:

  @a = ([1,2],[3,4],[5,6]);
  @transposed_list = transpose(0,1,@a);   # ([1,3,5],[2,4,6])

This is different to reshape (see "RFC 148") which does not reorder its elements:

  @a = ([1,2],[3,4],[5,6]);
  @reshaped_list = reshape([3,2],@a);   # ([1,2,3],[4,5,6])

transpose is its own inverse:

  @transposed_list = transpose(0,1,@a);   # ([1,3,5],[2,4,6])
  @orig_list = transpose(0,1,@transposed_list); # (([1,2],[3,4],[5,6])
  @a == @orig_list;   # true

If transpose refers to a dimension that does not exist, empty dimensions autovivify as necessary:

  @row_vector = (1,2,3,4);
  @col_vector = transpose(0,1,@row_vector);   # ([1],[2],[3],[4])

Reordering Dimensions

An alternative form of transpose uses the first argument as a list ref to specify a new order for the dimensions:

  transpose [0,3,4,1,2], @arr;

If some dimensions are not specified in the first argument, those dimensions are left in their current order:

  # Where @arr is a rank 5 array...
  transpose ([3], @arr) == transpose ([3,0,1,2,4], @arr);
  transpose ([0,3], @arr) == transpose ([0,3,1,2,4], @arr);

This syntax allows multidimensional arrays to be reduced along any dimension:

  @sumover_1st_dim = reduce ^_ + ^_, @arr[ 0..; |i; * ];
  @sumover_3rd_dim = reduce ^_ + ^_, transpose([3],@arr)[0..; |i; * ];

Note that reduce is from RFC 76, and |i is from RFC 207.


transpose does not make a copy of the elements of its arguments; it simply create an alias:

  @row_vector = (1,2,3,4);
  @col_vector = transpose(0,1,@row_vector);  # ([1],[2],[3],[4])
  $col_vector[[0,1]] = 0;
  @row_vector == (1,0,3,4);                  # True

Optional Extra: Dimension Insert

To move a dimension and insert it before some other dimension, the following syntax may be used:

  transpose ({3=>2}, @arr) == transpose ([0,1,3,2,4], @arr);

which inserts dimension 3 in front of dimension 2.


RFC 90 discusses possible approaches to implementing aliasing.


RFC 76: Builtin: reduce

RFC 90: Arrays: merge() and unmerge()

RFC 148: Arrays: Add reshape() for multi-dimensional array reshaping

RFC 207: Arrays: Efficient Array Loops