'''[http://www.tcl.tk/man/tcl/TclCmd/lappend.htm%|%lappend]''' appends [element%|%elements] to a list. ** Synopsis ** : '''lappend''' ''varName'' ?''value value ...''? ** Description ** `lappend` appends each ''value'' as an additional element to the list stored in ''varName'', and returns the value of ''varName''. `lappend` differs from `[append]` in that values are appended as elements in the list rather than raw text. `lappend` operates on the specified list in-place, so it is not necessary to assign the results of '''lappend''' to ''varName''. This is why the first argument to `lappend` is the name of a variable rather than the list value itself. It is an error if the value of the variable named ''varName'' is not a list. ======none % set x \{ ;# string that is not a list { % lappend x b ;# treat it as list unmatched open brace in list ====== Examples: ====== lappend auto_path /usr/local/lib/tcl8.5 #Does nothing but fail if listName is not a well-formed list. lappend listName ====== Incorrect usage: ====== #warning: bad code ahead set auto_path [lappend $auto_path /usr/local/lib/tcl8.5] lappend $listName ====== the problem in the set example is not the use of lappend in the [[ ... ]] construct, but the use of '''$auto_path''' as the first argument instead of '''auto_path''' (without the '''$'''). ** List Validation ** Another function of `lappend` is to validate a value as a well-formed list. When invoked with no `value`s, `lappend` simply makes sure that the value of the variable named by ''varName'' is a valid list, and returns it: [RS] 2006-10-01: [jcw] contributed this (for me) surprising [idiom]: ====== lappend var ====== does nothing, but creates ''var'' if it doesn't exist. Similar to, but simpler than: ====== if {![info exists var]} {set var ""} ====== This may however fail if `$var` holds a string that cannot be parsed as a list. [wdb]: It works, but it is some kind of ''dirty trick'' as it is based on some Tcl-internal optimizing located far out of documented behaviour. The greater danger is '''not''' to throw an error. Exemplum gratia, here [lappend] works as you describe: ======none % set a "a {b} c" a {b} c % lappend a a {b} c ====== but here not: ======none % set a "a {b} c" a {b} c % lappend a x a b c x ====== Unintended side effect: word b has "forgotten" its surrounding braces as they are not necessary for identifying b as a word . I don't think that this will fit to the category [quick'n'dirty] as it is perhaps dirty enough but not quick if you are hunting the resulting bugs on friday afternoon ;-) [Lars H]: Well, if you care about the braces, then apparently you don't merely see the value as a list, and in that case using [lappend] probably isn't the right thing to do (as ''it'' will only respect the list interpretation of the value). [jcw] has also been seen using [append] in the same way, when the value is a more general string. ** Unique [[lappend]] ** [jmn] 2008-06-04: I find myself using code like the following very often: ====== if {$element ni $list} { lappend list $element } ====== I know it's not much code.. but It seems to me it'd be neat to have an option so you could instead do something like: ====== lappend -ifmissing list $element ====== jcw: This indicates you're using a list as a set. You could also consider using 8.5's `dict set list $element {}` for a slightly different approach. [AMG]: Faster, too, though it honks up the string representation to have every other word be empty string. Use [[[dict keys]]] to get your data back without the empties. If you don't have [[[dict]]], use [[[set] list($word) {}]] instead, then [[[array names]]] will give you the list of word. Though you're using [ni], so I'm sure you will have [[dict]]... [RS] 2008-06-04: I just add a convenience proc whenever I need that functionality: ====== proc ladd {_list el} { upvar 1 $_list list if {$el ni $list} {lappend list $el} } ====== ** List concatenation ** [AMG]: [[lappend]] can be used with the [{*}] expansion operator to concatenate lists. ====== lappend listVariable {*}$otherListVariable lappend listVariable {*}[scriptReturningList] ====== But what if you don't have [{*}]? Then you can use [[[eval]]] or [[[concat]]]. Here's a demonstration of the latter: ====== set listVariable [concat $listVariable $otherListVariable] set listVariable [concat $listVariable [scriptReturningList]] ====== There is one subtlety being missed. [[lappend]] is a [Dangers of creative writing%|%creative writer], meaning that it creates the named variable if it doesn't already exist. The above code will not do this since it starts by taking its value to get the first argument to [[concat]]. Solution? Use [[[append]]] to append empty string to the variable, which creates it if it's not there but otherwise leaves it unchanged. What's more, [[append]] returns the variable's value, so it all fits in a one-liner, [functional] context: ====== set listVariable [concat [append listVariable {}] $otherListVariable] set listVariable [concat [append listVariable {}] [scriptReturningList]] ====== ** See also ** [list]: <> Tcl syntax help | Arts and crafts of Tcl-tk programming | Command