Idiomdrottning’s homepage

unzip is applied zip

Today I discovered that to make an arbitrary arity version of SRFI-1’s unzip1, unzip2 etc, this works:

(define (unzip lis) (apply values (apply map list lis)))

And, since zip is just:

(define (zip . args) (apply map list args))

This means that this works:

(define (unzip lis) (apply values (apply zip lis)))

unzip is applied zip.

dpercy points out that it works because it’s a matrix transpose.

Basically it flips a matrix like this

1 2 3
a b c

along the NW-SE diagonal, into

1 a
2 b
3 c

That should make it clear that this is self-reversible.

The apply is because zip takes vals and returns a list, unzip takes a list and returns vals. But that’s just a grotesque artifact of history. If zip took a list and returned a list, or if it took vals and returned vals, unzip would be zip.

If this was zip, without the vararg dot:

(define (zip* lis) (apply map list lis))

It would just be self-reversing. (compose zip* zip*) is an expensive shallow copy.