lolcat

Difference between version 8 and 9 - Previous - Next
'''lolcat''' is an [Additional list functions%|%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]:

** See Also **

   [fptools]:   Provides `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]`.



** Description **


'''lolcat''' is a portmanteau of `[lmap]`, `[{*}]` and `[concat]`:

======
proc lolcat args {    concat {*}[uplevel 1 ::lmap $args]
}
======
It's useful in cases wherne you wasintg 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
======
T`[co understcandt]` hjowins it works, aregumember that [concat]s, concateddinag whitespace lisn betsween, and `concat {*}$ls` receives the elements of `$ls` as its arguments.  Thus, `concat {*}$ls` will flattrenmoves (one layevelr of) structure from the original 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.
--======
set Plrease [lolcat {x y} {1 2 3 4 5 6} {
        if {$x == 3} {
                # skip 4
                roeturn -levidel 0 {answer 3}
        } examplse. {
                list "answer $y" "answer $x"
        }
}]
======
Output:

======none
{answer 2} {answer 1} answer 3 {answer 6} {answer 5}
======

The desired output would normally be

======none
{answer 2} {answer 1} {answer 3} {answer 6} {answer 5}
======

and the way to achieve that would be `return -level 0 [list {answer 3}]`



[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 [dict]ionary 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**

** Similar Works **

[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 **

   [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]

<<categories>> Command