Purpose: Proposal for an official extension of additional list operations. The proposal is based on the Chart of existing list functionality and the wishlist in Additional list functions.
Please note: This proposal discusses only the functionality to include in the extension, but neither command names nor implementation issues (like C vs. Tcl, etc.).
Handling lists as sets: Moved to the Chart of proposed set functionality.
Peter De Rijk (2003) Several of the commands moved to sets here, present another functionality on lists because of the implementation of sets as hashes: The order of elements in a set will not necessarily be retained. Things like removing a set of elements from a list, or checking for presence of an element while retaining the list order are useful.
Lists as queues and stacks: Moved to the Chart of proposed queue functionality and Chart of proposed stack functionality.
Other generic accessor and manipulator functionality
Remark: TclX combines both of the above in one function, as does the kernel. To discuss.
The last three functions could be combined to form a sort of generalized lappend, with options controlling the behaviour.
Uses: Scatter/gather operations, permutations.
Both of the above can be used as the base of several other nice functionalities (see below). And they might be usable for the implementation of some of the functionality listed above too.
Wouldn't a 'map' type function equate this? -FW
Searching in lists.
Special functions, not fitting anywhere else
List Manipulation Performance
It goes without saying that we would like the list manipulation routines to be fast and efficient. Manipulation routines (sometimes called mutators) like insert, replace, remove (described above) change the state of objects. Unfortunately, the core list routines almost always require the list to be passed by value. For example, to simply replace a single element in a long list, you have to copy the list like this:
set myList [lreplace $myList 20 20 "new Element"]
Tcl's object model is smart enough that it doesn't copy all elements in the list, but it does have to make a new list object of pointers to the list elements. If the list is short (100 elements) then this isn't a big deal. If your list is long (1000+) then list manipulation will be slow.
One way to avoid extraneous list copies is to offer additional list functions which can manipulate the list contents "in place," without the extra overhead of list copies. It is necessary to refer to the lists by name instead of by value, just as the core command lappend does. As an example (although we're not specifying syntax here!), we could replace a single element in a long list with a command like
replace-in-place myList 20 20 "new Element"
Donal Fellows suggests a K() operator on the Tcl Performance page which can help with pure-Tcl implementations of these "in place" operations.
RWT
DKF: As an aside, there are four classic combinators from theoretical CS: o, I, K and S.
Note that SKK is equivalent to I. There is a theorem that states that the calculus of the combinators S and K is equivalent to Lambda Calculus, and is therefore Turing powerful.
End of non-Tcl diversion!
-- AK
escargo 16 Marc 2003 - In my data structures classes from ages gone by, we sometimes discussed self-organizing data structures, especially linear lists that had the property of dynamic reordering based on access. There were two often-used heuristics applied:
These are specific instances of moving an element either k positions from the front or k positions forward of its current position.
When using linear searches with bursty access patterns, these heuristics can speed up access.
Michael Schlenker 17 March 2003 Basically you're talking about Result Caching.
AK: Not quite. A list of this type can actually be used when managing caches (LRU, i.e. Least Recently Used) to determine which part of the cache to overwrite if the cache is full and something is added. Namely the elements at the end of the list as they are used least.
RS 2004-11-17: See A size-bounded cache for an implementation of that - and here's the LRU functionality for a list alone, in case someone needs it (e.g. for a list of the n files most recently opened):
proc lru {listVar maxLength item} { upvar 1 $listVar list if {![info exists list]} {set list {}} set pos [lsearch $list $item] set list [lreplace $list $pos $pos] lappend list $item if {[llength $list] > $maxLength} {set list [lrange $list 1 end]} set list }
LV How does the above proposal match against the current tcllib extended list command (struct::list) ? Is anyone considering adding more of the above functionality into tcllib?
Wouldn't the following procedure fit into tcllib?
proc ltuple {multilist {tuplelen 2}} { # init a list res (result) for {set i 0;set res ""} {$i<$tuplelen} {incr i} {lappend res ""} if {[llength $multilist]%$tuplelen!=0} { error "incorrect tuple length, or input mismatch" } for {set i 0;set j 0;set l [llength $multilist]} {$i<$l} {incr i;incr j;set j [expr {$j%$tuplelen}]} { lset res $j [concat [lindex $res $j] [lindex $multilist $i]] } return $res } # Example : array set table {id 2 name MAIN desc "Main process"} foreach {keys values} [ltuple [array get table]] # $keys={id name desc} and $values={2 MAIN {Main process}}