lshift - shift list and return first element : '''lshift''' ''listVar'' This is not a command included in Tcl, but rather a common 'idiom' for in-place list manipulation used e.g. for implementing queues are for command line processing. A proper implementation should throw an error when listVar does not exist, and also when listVar contains the empty list (or string). ---- ** Implementations ** The following is taken from [Tcl Gems] though slightly modified: ====== proc lshift listVar { upvar 1 $listVar l set r [lindex $l 0] set l [lreplace $l [set l 0] 0] return $r } ====== You can use this programming idiom also without having the lshift command, e.g. with the [K] combinator: ====== K [lindex $l 0] [set l [lreplace $l [set l 0] 0] ====== Or more generalized: : '''lshift''' ''listVar ?count?'' Shift list ''count'' elements and return the respective elements. ====== proc lshift {listVar {count 1}} { upvar 1 $listVar l set r [lrange $l 0 [incr count -1]] set l [lreplace $l [set l 0] $count] return $r } ====== And finally a full fledged one with error handling: ====== proc lshift {listVar {count 1}} { upvar 1 $listVar l if {![info exists l]} { # make the error message show the real variable name error "can't read \"$listVar\": no such variable" } if {![llength $l]} {error Empty} set r [lrange $l 0 [incr count -1]] set l [lreplace $l [set l 0] $count] return $r } ====== ** Different Interpretations ** In [lshift -Adding Unique Items to Lists of Fixed Length] the command lshift puts an element on a list if it is not already there. It is used to implement a 'recently used' list ** Nifty Tricks ** In [Tcl Gems] lshift is used for command line arguments processing. In [Stacks and Queues] the genial [RS] names lshift '''qpop''' - if push appends to the end, then pop pops from the end (stack) and lshift (qpop) pops from the front (queue). [LEG] would like to contribute the following method to iterate over lines of text, whether stored in a file or in a variable: ====== proc vGets {listVar lineVar} { upvar 1 $listVar l $lineVar line if {[catch {lshift l} line]} {return -1} else {string length $line} } if {..} {# text in variable "text" set lines [split $text \n] set getLine vGets } else {# text in channel fd set lines $fd set getLine gets } while {[$getLine lines line]!=-1} { # do something with the line .. } ====== ---- !!!!!! %| [Category Command] |% !!!!!!