***COMMAND*** concat - Join lists together ***USAGE*** : '''concat''' ?''arg arg ...''? ***CONTEXT*** TCL core command ***DESCRIPTION*** Trims the leading and trailing whitespace from the arguments and joins them together, adding a white space between them. If all the arguments are lists, this has the same effect as concatenating them into a single list, hence the name "concat". When the arguments are not well-formed lists, the results can be unexpected. It permits any number of arguments; if no args are supplied, the result is an empty string. ***MAN PAGE*** http://www.tcl.tk/man/tcl8.5/TclCmd/concat.htm ***SEE ALSO*** [list], [append] ***EXAMPLES*** ====== concat a b {c d e} {f {g h}} ====== will return '''a b c d e f {g h}''' Arguments that are not well-formed lists: ====== concat " a b {c " d " e} f" ====== The result is '''a b {c d e} f''' Note that the concatenation does not remove spaces from the middle of its arguments, so the command: ====== concat "a b c" { d e f } ====== will return '''a b c d e f''' (i.e. with three spaces between the a, the b and the c). use [lappend] to concatenate lists while making sure the inputs are valid lists: ====== lappend mylist {*}$myotherlist ====== See [Concatenating lists] for a timing comparison of various methods. Other methods of putting strings together include: * string substitution set a "abc" set b "123" set c $a$b * [format] command set c [format "%s %s" $a $b] * [append] (for strings) * [lappend] (for lists) * [join] join [list $string1 $string2] <> ---- To concat an explicit empty list and another list use: ====== set a [concat {{}} {a} {b}] ====== '''[DGP]''' No, that example concatenates three single-element lists into a single three-element list. Likewise, so does ====== set a [concat [list {}] a b] ====== Don't confuse an empty list (a list of 0 elements), with a single-element list whose element happens to be an empty string. Also don't imagine that braces have magic list-ifying powers. [Lars H]: Good advices when experimenting with these things are: 1. Put all arguments you want to experiment with in variables, to avoid confusion like above of what is done by the parser and what is done by the command. 2. Test the values you put in variables using [llength], [lindex], etc. to see that it really is what you want it to be. ---- '''Anonymous:''' Hmm, so what is the proper syntax for concatenating an empty list and another list? Perhaps ======none % set a [concat [list] [list a b]] a b ====== is right? Let's see: ======none % llength $a 2 ====== That in theory could be right - the empty list would be entry 1 and the a b list would be two. What happens when I look at entry 1? ======none % lindex $a 0 a ====== Whoops... looks like that code, above, doesn't do it right in ======none % info patchlevel 8.5a6 ====== In fact, ======none % llength [list] 0 ====== says that an "empty list" isn't a list at all. I'm uncertain why the original poster was looking for a list concat'ed to an empty list... [Lars H]: No, that says the length of an empty list is 0. If by "concatenating two lists" one means "form a list which contains first all the elements of the first list, then all the elements of the second list", then what [concat] does above is exactly right. You rather seem to want to form the list of the two given lists, which rather is what [list] would do. ---- Concatenating the sublists of a list (e.g. a matrix) is best done with [join]. [Lars H]: That is a rather controversial statement. An obvious problem with using [join] is that it operates on the string representations of the sublists and thus loses any internal representations that may exist. If [tcl_precision] is less than its maximum, then this will even result in loss of precision for numerical data! Also, I would like to see proof that using join can never result in the creation of malformed lists before trusting [join] to do this. In Tcl 8.5, the proper way will be to use [{*}]: ====== concat {*}$matrix ====== but until {*} becomes available, we can make do with ====== eval [list concat] [lrange $matrix 0 end] ====== or ====== eval [linsert $matrix 0 concat] ====== In most reasonable cases, ====== eval [list concat] $matrix ====== will work as well, but it will give unpleasant surprises if there is a newline character between two elements of the $matrix. [DBaylor] I find the behavior of concat bizarre. Numerical precision is lost with concat also - sometimes. At least with join you know you're losing precision. Here's an example: ====== set a [expr {1.0 / 3.0}] set list_aa [concat [list $a] [list $a]] # prints 1.0 puts [expr {3.0 * [lindex $list_aa 0]}] set list_a0 [concat [list $a] [list]] # prints 0.9999... puts [expr {3.0 * [lindex $list_a0 0]}] ====== [Lars H]: It seems you have found a counterexample to the rule that "The result of [list] is a [pure list]." -- namely that the empty list returned by [list] is just the empty string. I'd say this is a bug. Do you wish to report it, or should I? (That it matters at all is of course also a bug, but that one is deep and harder to fix. [KBK] has a [TIP] for 8.5 which will address it.) [AMG]: Which TIP? [Lars H]: TIP#132 [http://tip.tcl.tk/132.html]. It fixes the issue that conversion to string may cause loss of precision. [AMG]: Oh, I misunderstood. I thought the TIP would be to make [[[list]]] return a [pure list], not an empty string. But I do appreciate what #132 does. [LV]: 2006 Dec 05: so, did the "[[list ]] " is not returning a pure list report ever get filed at tcl.sf.net? [Lars H]: Yes, it is #1143805 [http://sourceforge.net/tracker/index.php?func=detail&aid=1143805&group_id=10894&atid=110894]. The reply was mostly that "we prefer it the way it is; closing report". ---- [DKF] says, on [comp.lang.tcl]: In Tcl 8.5, you will be able to simulate the effects of a real list-oriented concatenation operator with [list] and the new [{*}] syntax, like this: ====== # Instead of: set foo [lconcat $bar $boo $spong] set foo [list {*}$bar {*}$boo {*}$spong] ====== ---- [wdb] Back to earth, I found this surprising behaviour: % info patchlevel 8.4.13 % set l [concat \{ a b c] { a b c % lindex $l 0 unmatched open brace in list % I expected [concat] either to return a proper list or --- if that doesn't work --- raise an error, but never a string which cannot be parsed to a list. In my humble understanding, this is a bug. [AMG]: concat is defined in terms of ''string'' concatenation; ''list'' concatenation is "merely" an optimization applied when all arguments are [pure list]s [http://wiki.tcl.tk/1037#pagetocae67ded1] [http://tcl.cvs.sourceforge.net/viewvc/tcl/tcl/generic/tclUtil.c?revision=1.114&view=markup#l_1127]. In your example, concat's first argument is not a valid list, let alone a pure list. `[[[string is] list \{]]` returns 0. concat's remaining arguments aren't pure lists either, even though they're valid lists. <> <> syntax | Arts and crafts of Tcl-Tk programming | Command | String Processing