[Richard Suchenwirth] 2005-04-02 - [lmap] is a "collecting [foreach]" which returns a list of its results. In [Jim] it is built in, but it can be easily had in pure Tcl: proc lmap {_var list body} { upvar 1 $_var var set res {} foreach var $list {lappend res [uplevel 1 $body]} set res } Several usage examples are at [Multiplication tables]. [Lmap] is a compromise between Tcl and the classical [functional programming] function [map], in that it takes a "quasi-[lambda]" which is split up into the ''_var'' name and the ''body'' arguments. However, this style is well-known from [foreach], and somehow reads better: lmap i {1 2 3 4 5} {expr $i*$i} vs. map [lambda i {expr $i*$i}] {1 2 3 4 5} ---- [Jim]'s [lmap] uses [continue] to skip the accumulation of the current iteration, so it works like [map] and [filter] at the same time. In Jim lmap supports multiple lists in input like the real [foreach], so you can do interesting things like this: . lmap a {1 2 3} b {A B C} {list $a $b} {1 A} {2 B} {3 C} Multiple lists + accumulation + continue to skip makes it also somewhat similar to list comprehension (but simpler to use in the my (SS) opinion). ---- A cute variation is ''fmap'' (influenced by ApplyAll in Backus' FP; [Joy] has a comparable operator in ''cleave'') which maps a list of functions on one argument: proc fmap {functions x} {lmap f $functions {$f $x}} Then we can write a file reader like this: proc << filename {lindex [fmap {read close} [open $filename]] 0} [NEM] I like that one! There is an mmap function that I wrote with [Monadic TOOT] which is similar to lmap (look about 1/3 way down that page). Instead of using continue, it uses a maybe monad to decide which results to accumulate. (Actually, it's quite general, and any monad could be used). ---- [iu2] I like to eliminate the "helper variables": proc lmap {list body} { upvar 1 0 var ;# $0 will be available automatically! set res {} foreach var $list {lappend res [uplevel 1 $body]} set res } So we can write lmap {1 2 3 4 5} {expr $0*$0} As I often replace the original list variable with the mapped list, instead of set list [lmap $list {expr $0 $0}] I can do lmap! list {expr $0 * $0} wher lmap! is proc lmap! {listvar body} { upvar 1 $listvar res set res [lmap $res $body] } ---- [Category Functional Programming]