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
PYK 2016-01-09 cautions:
lolcat requires that the result of the
lmap body be a list, not a simple value. Otherwise, data might get munged.
-- Please provide an example.
PYK 2016-04-19:
join is a little more concise and efficient, and the
1 in
uplevel isn't strictly necessary since
lmap can't be interpreted as a level:
proc lolcat args {
join [uplevel lmap $args]
}
-- Timing trials indicate that the
join version is some 8% slower. YMMV.
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!
Similar Works edit
AMG: [lolcat] resembles [
lcomp]:
% lolcat {a b} {1 2 3 4} {list $b $a}
% lolcat a {1 3} b {2 4} {list $b $a}
% lcomp {$b} {$a} for {a b} in {1 2 3 4}
% lcomp {$b} {$a} for a in {1 3} and b in {2 4}
All return
2 1 4 3. The differences are:
[lolcat] | [lcomp] |
---|
Result generator is last argument | Result generator is first argument(s) |
Result generator is one argument | Result generator is one or more argument(s) |
Result generator is Tcl script | Result generator is expr expressions |
No noise words | Supports numerous tokens such as for |
While I'm on the subject,
Brush offers (will offer) capability very similar to [lcomp], though the language-level syntax is different:
% collect b a for (&a &b) in (1 2 3 4)
% collect b a for &a in (1 3) and &b in (2 4)
See Also edit
- 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