zipn()

drhyde on 2003-04-26T20:08:28

sub zipn {
    local $[ = 0;
    [
        map {
            my $index = $_;
            map {
                defined($_[$_][$index]) ?
                    $_[$_][$index] :
                    ''
            } 0..$#_
        } 0 .. maximum(map { $#{$_[$_]} } 0..$#_)
    ]
}

sub maximum { local $[ = 0; ($#_ == 1) ? ( ($_[0] >= $_[1]) ? $_[0] : $_[1] ) : maximum(maximum($_[0], $_[1]), @_[2..$#_]); }


Call it like so:
zipn([1,2,3], [4,5,6], [7,8,9,10])


and it'll return this:
[1,4,7,2,5,8,3,6,9,'','',10]


What fun! Note that if any of the arrays are too short, it fills in the blanks with the empty string, cos that's what I needed at the time. Changing it to emit undefs would be trivial. And yes, the maximum function is hideously inefficient, but I enjoy recursion.


local $[ = 0;

rafael on 2003-04-26T21:16:37

This is unnecessary, and in fact, I'm surprised it's not a runtime error. $[ is lexical. Quoting perlvar :
As of release 5 of Perl, assignment to $[ is treated as a compiler directive, and cannot influence the behavior of any other file.

Re:local $[ = 0;

drhyde on 2003-04-26T23:04:57

If I had packaged that up in a neat little module on its own then yes, I wouldn't have bothered, but I didn't, and if someone had cut n' pasted it into some of their code where they'd been messing with $[, then I need to set it myself.

I fail to see anything in that snippet from the man page which suggests that it is either unnecessary or an error.

Re:local $[ = 0;

rafael on 2003-04-27T19:22:47

You don't understand me : $[ acts as a pragma. It's not file-scoped, it's lexical. Using local() on it is a null operation. The perlvar phrasing is misleading, I'll see how to change it (except the part where it is said that its use is highly discouraged).

Re:local $[ = 0;

rafael on 2003-04-27T20:35:24

OK, I was wrong, it appears that $[ leaks out of some scopes at compile time, so it's not strictly equivalent to a pragma. So the following prints, undocumentedly, '001' :

print $[;
if (0) { local $[ = 1; }
print $[;
if (0) { $[ = 1; }
print $[;

Docs clarified

rafael on 2003-04-27T21:02:43

like this. Blogs rule.

Re:Docs clarified

drhyde on 2003-04-27T22:20:51

Eeuuww! That's *really* nasty! If I were to ever be crazy enough to set it to something other than zero, I think I'd want to compute the new value at run-time. But thankfully, whilst I may be a crazy loon, I'm not *that* crazy.

max()

bart on 2003-04-26T23:51:05

max() is in the module List::Util. Depending on the platform, it may be in XS, or in plain perl (the fallback). Anyway, it's not necessary to reinvent that wheel.

Re:max()

drhyde on 2003-04-27T15:24:15

If I'd wanted to do things the "right" way, I wouldn't have written "And yes, the maximum function is hideously inefficient, but I enjoy recursion.". Obviously.