[[...]] [Steve Cassidy]: "[Trf] lets you zip up a bit of data but doesn't provide the machinery to zip directories or files. mkZipLib [http://mkextensions.sourceforge.net/] provides such an interface as does zvfs [http://www.hwaci.com/sw/tobe/zvfs.html]. More up to date is the zipvfs package which is part of [tclvfs] but that doesn't seem to be working cleanly yet and requires tcl8.4 features." http://www.equi4.com/critlib/zipper.README http://www.equi4.com/critlib/zlib.README See also [Using a zip file as a Tcl Module]. See also [Using zipper to create zip files]. Also, explain pkware vs. winzip vs. zLibDll. ---- [NEM] zip is also the name of another [functional programming] classic. You can think of it as a function that takes a bunch of "columns" (think relational) and returns a list of "rows": ====== proc zip {cola colb} { set ret [list] foreach a $cola b $colb { lappend ret [list $a $b] } return $ret } zip {1 2 3} {a b c} ;# returns {{1 a} {2 b} {3 c}} ====== You can generalise zip to zipWith which applies an arbitrary function on each pair of values from the columns: ====== proc apply {func args} { uplevel #0 $func $args } proc zipWith {f cola colb} { set ret [list] foreach a $cola b $colb { lappend ret [apply $f $a $b] } return $ret } interp alias {} zip {} zipWith list ====== You could further generalise the function to take an arbitrary number of columns. I'll leave that, and the reverse unzip operation as exercises. See also [fold], [filter], [iterators] and [map]. ''[Lars H]: Isn't that more commonly known as "transposing"? See [Transposing a matrix].'' [NEM]: Depends who you ask. `zipWith` is more general, though. [AMG]: "list" isn't a valid lambda, so it's not directly usable with the Tcl 8.5 [[[apply]]] command. Here's an 8.5-compatible version. It uses single-argument [[[lindex]]] instead of [[[list]]] to avoid adding an extra level of list nesting. (Single-argument [[lindex]] simply returns its argument, even if its argument isn't a valid list.) ====== interp alias "" zip "" zipWith {{args} {lindex $args}} ====== ---- [AMG]: Implementation using [lcomp]: ====== proc zip {cola colb} { lcomp {[list $a $b]} for a in $cola and b in $colb } ====== Here's a version that handles an arbitrary number of columns: ====== proc zip {args} { if {[llength $args]} { for {set i 0} {$i < [llength $args]} {incr i} { append expression " \$$i" lappend operations and $i in [lindex $args $i] } lset operations 0 for lcomp \[list$expression\] {*}$operations } } ====== Also, I'll take your unzip challenge. ;^) ====== interp alias "" unzip "" zip ====== As [Lars H] pointed out, zip is transpose, so using it twice gives back the original input. Examples: ====== % zip {a 1} {b 2} {c 3} {a b c} {1 2 3} % unzip {a b c} {1 2 3} {a 1} {b 2} {c 3} ====== <> Compression | Functional Programming