Skip navigation

Since I had to spend ten minutes on Dukgo finding out what this ‘Cartesian product’ is called (and boy, it’s going to be embarrassing if I got this wrong from the beginning), for those with a shaky background in math like myself, here’s a simple description:

You have two sets, A and B. A contains 1, 2, 3, 4; B contains a, b, c, d. The Cartesian product of A and B would be 1a, 1b, 1c, 1d, 2a, 2b, 2c, 2d, 3a, 3b, 3c, 3d, 4a, 4b, 4c, 4d.

With that said, let’s get on with the Perl!

#! /usr/bin/perl
use strict;
use warnings;
use 5.010;

my @significant_array   = 1..4;
my @meaningful_array    = "a".."d";

Now, the (my) usual way to calculate the Cartesian product would be to use a map within a map:

my @mapped_cartesian_product = map {
        my $first = $_;
        map $first . $_, @meaningful_array;
    } @significant_array;

say join(', ', @mapped_cartesian_product);

(Or you could be smart and use List::Gen’s cartesian function, but that’s another story.)

So here’s today’s trick: You could use <>; as well:

say join(', ', <{1,2,3,4}{a,b,c,d}>);

However, if you tried to use this with the arrays defined earlier, like:

say join(', ', <{@significant_array}{@meaningful_array}>);

This outputs, ‘, 2, 3, 4}, b, c, d}’… Not really what we wanted to get.

To understand why this happens, ┬áthere’s something simple to know first. <> is actually two operators, all for the price of one; The first is the usual thing we do to read from a filehandle. The second is slightly more interesting; It calls CORE::GLOBAL::glob(),

If what’s within the angle brackets is neither a filehandle nor a simple scalar variable containing a filehandle name, typeglob, or typeglob reference, it is interpreted as a filename pattern to be globbed, and either a list of filenames or the next filename in the list is returned, depending on context.

(From perldoc perlop).

Using glob’s documentation, it’s not too hard to find the problem with our previous example: <{@significant_array}{@meaningful_array}> is actually glob "{@significant_array}{@meaningful_array}", and an array in a double quoted string interpolates as a space-delimited list of its elements, which glob splits on!

So to get this to work, we need to set $” (or $LIST_SEPARATOR if you use English;) to a comma:

my @globbed_cartesian;
{
    local $" = ',';
    @globbed_cartesian = <{@significant_array}{@meaningful_array}>;
}

Or maybe:

my @doglobbed_cartesian = do {
        local $" = ',';
        <{@significant_array}{@meaningful_array}>
        };

I’d be hard-pressed to find an actually useful situation for this construct (I’ll admit I’m not a terribly imaginative person), and it could really hurt maintainability… But this, too, is Perl.

And it never hurts to know more Perl!

Credits should go where they are due: I discovered this construct while reading juster’s comment on curiousprogrammer.wordpress.com

..I guess the title is a little bit disingenuous, in that it’s really ‘Using glob to find etc’.

About these ads

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

Follow

Get every new post delivered to your Inbox.

%d bloggers like this: