Version 3 of lolcat

Updated 2015-06-02 01:58:42 by aspect

lolcat is an additional list function which aspect uses almost every day. Once you come to love it, you will too!

It's a portmanteau of lmap, {*} and concat:

proc lolcat args {
    concat {*}[uplevel 1 lmap $args]
}

It's useful in cases where you want to lmap, but the body might need to yield multiple results for a single iteration. Here's a simple example:

% lolcat {x y} {1 2 3 4} {list $y $x}
2 1 4 3
% lolcat x {1 2 3 4} {if {$x%2} {list $x $x} else {list $x}}
1 1 2 3 3 4

To understand how it works, remember that concat concatenates lists, and concat {*}$ls receives the elements of $ls as arguments. Thus, concat {*}$ls will flatten (one level of) a list:

% concat {*}{{1 2} {3 4 5} {6 {7 8}} 9}
1 2 3 4 5 6 {7 8} 9
# equivalently:
% concat {1 2} {3 4 5} {6 {7 8}} 9
1 2 3 4 5 6 {7 8} 9

One neat extension on lolcat is dictify:

proc dictify {cmdPrefix ls} {
    lolcat x $ls {
        list $x [uplevel 1 $cmdPrefix [list $x]]
    }
}

This allows you to make a dictionary whose keys are a list, and values are the result of evaluating a command on each element.

% dictify {expr 2**} {1 2 3 4 5}
1 2 2 4 3 8 4 16 5 32

Or more elaborately:

% proc pdict {d} {array set {} $d; parray {}}
% pdict [dictify {tcl::pkgconfig get} [tcl::pkgconfig list]]
debug              = 0
threaded           = 1
profiled           = 0
64bit              = 0
optimized          = 1
mem_debug          = 0
compile_debug      = 0
compile_stats      = 0
libdir,runtime     = /home/tcl/lib
bindir,runtime     = /home/tcl/bin
scriptdir,runtime  = /home/tcl/lib/tcl8.6
includedir,runtime = /home/tcl/include
docdir,runtime     = /home/tcl/man
libdir,install     = /home/tcl/lib
bindir,install     = /home/tcl/bin
scriptdir,install  = /home/tcl/lib/tcl8.6
includedir,install = /home/tcl/include
docdir,install     = /home/tcl/man

The name comes courtesy hypnotoad - previously I called this procedure lconcat, which is obviously a terrible name, and I only stuck with for lack of a better alternative. It took the toad's genius to find this proc's correct name, which just goes to show: give a dog a bad name, and it will stick ... but a cat can change its stripes!

See Also

fptools
contains a proc lmultimap which offers a different way to have multiple results from mapping over a single list
map in functional programming
another small but powerful variation on lmap