lpop - remove last element of list variable : '''lpop''' ''listVar'' This is not a command included in Tcl, but rather a common ''idiom'' for in place list manipulation used e.g. for implementing stacks. '''lpop''' removes the last element from the list in ''listVar'' and returns it. ''listVar'' is altered in place. See also: [lpush] alias [lappend] as the "reverse" operation of lpop, [lprepend], [lshift] as the counterpart operating on the other end of the list, as well as [Chart of existing list functionality]. ---- ** Different Interpretations ** In [ExtraL], the command accepts an optional parameter pos: : '''lpop''' ''listVar ?pos?'' If ''pos'' is given, the element at position ''pos'' of the list is 'popped' off the list instead of the last element. [LEG] would prefer to interpret the optional argument not as a position, but rather as the count of elements to pop of the tail of the list. _ '''lpop''' ''listVar ?count??'' This would harmonize better with the semantics of lappend, alias lpush, which append a number of elements to a list. Maybe `lpluck list ?pos?`, would be a better name for the [ExtraL] functionality, where position would be specified just like in [lindex]. In [Bag of algorithms], [The anatomy of a bytecoded command] and [Searching A Star In Space], amongst others, lpop pops off the first element of the list. This is kind of [http://en.wikipedia.org/wiki/Pushmi-pullyu#The_Pushmi-pullyu%|%pushmi-pullyu%|%]: On one side a convenient implementation of the stack push command s ''lappend listVar element''. Here the last element of the list (the 'right-most') has to be seen as the top of the stack, which might appear counterintuitive to some people. Those would, on the other side rather push elements on the stack 'to the left', and pop them from there (index 0 of the list). A more convenient name for this second interpretation of lpop might be [lshift]. Since the Tcl-core does not provide an opposite of the [lappend] command, implementing a stack where the top element is at list position 0 (or 'left-most') has poorer performance. [AMG]: A stack whose top is at list position zero can be implemented as follows: ====== proc push {listvar elem} { upvar 1 $listvar list set list [concat [list $elem] $list] } proc pop {listvar elemvar} { upvar 1 $listvar list $elemvar elem set list [lassign $list elem] } ====== ** Implementations ** This one, copied from [Performance of Various Stack Implementations], contributed by [Lars H], is simple and best in performance. ====== prop lpop listVar { upvar 1 $listVar l set r [lindex $l end] set l [lreplace $l [set l end] end] ; # Make sure [lreplace] operates on unshared object return $r } ====== Note: the 'set l end' idiom is a trick to "unset" l and at the same time provide the verb 'end' to lreplace resulting in 'lreplace $l end end'. You can use this programming idiom also without having the lpop command, e.g. with the [K] combinator: ====== K [lindex $l end] [set l [lreplace $l [set l end] end] ====== This one is a similiar implementation with optional element count: ====== proc lpop {listVar {count 1}} { upvar 1 $listVar l set r [lrange $l end-[incr count -1] end] set l [lreplace $l end-$count [set l end]] set r } ====== And the following is a full fledged version with error handling: ====== proc lpop {listVar {count 1}} { upvar 1 $listVar l if {![info exists l]} { error "can't read \"$listVar\": no such variable" } if {![llength $l]} {error Empty} set r [lrange $l end-[incr count -1] end] set l [lreplace $l end-$count [set l end]] return $r } ====== ---- !!!!!! %| [Category Command] |% !!!!!!