Another article of the series “Yet Another Perl 6 Operator”
Perl 6 provides an operator 'X', the cross operator, which combines its list operands into a sort of cartesian product of these arguments.
1,2 X 3,4 # (1,3), (1,4), (2,3), (2,4) 1,2 X 3,4 X 5,6 # (1,3,5), (1,3,6), (1,4,5), ..., (2,4,6)
The 'X' operator returns all possible lists formed by taking one element from each of its list arguments. The ordering of the returned lists is such that the rightmost elements vary fastest. Hence,
<a b> X (1,2)
ends up with
('a', 1), ('a', 2), ('b', 1), ('b', 2)
where the first elements come from <a b> and the second elements from (1,2).
In @ (list) context, the result becomes a flat list, while in @@ (splice) context it turns into a list of arrays.
say @(<a b> X 1,2) 'a', 1, 'a', 2, 'b', 1, 'b', 2 say @@(<a b> X 1,2) ['a', 1], ['a', 2], ['b', 1], ['b', 2]
The operator is list associative, so that @a X @b X @c produce a list of three-element lists. If any of the lists is empty, you will end up with a null list.
The cross operator also plays nicely with unbounded lists. But only the leftmost argument can be usefully an infinite list, or else some elements (other than the first ones of the
next arguments) will never be seen.
Just like the zip operator, the cross operator provides a handy operation on lists avoiding the need to code it with basic operations (like nested loops or maps). That avoids the need for clustered low-level coding when implementing some high-level algorithms.
For instance, data structures like rectangular boards can be generated from simple Perl 6 expressions, like:
# tic-tac-toe slots 0..^3 X 0..^3 # chess board squares 'a'..'h' X 1..8
Next article is due next Monday (Dec 24, 2007).


^3 X ^3
instead of
0..^3 X 0..^3
would work as well, no?
How often do you need this? Wouldn't it be much better to have this in a module?
@Elias Pipping: you are absolutely right.
^3 X ^3is just the same as0..^3 X 0..^3.@Ask Solem: That will depend on the type of programming you do. The availability of features as core also affects what people feel immediately at easy to add to their code. How many times you've heard people complain that X is a handy module, but that they prefer to not add this as a dependency in their code?
@Adriano Ferreira: I meant better as in not having it as an operator, but as a method in a class. It could just as well be in core.