Version 15 of concat

Updated 2005-02-09 10:42:10

Documentation for concat can be found at http://purl.org/tcl/home/man/tcl8.4/TclCmd/concat.htm

When concat puts its arguments together, it separates them with a space.


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.

When does one use concat compared to other Tcl methods of putting two strings together?

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
       set c [format "%s %s" $a $b]

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 instead be

  concat {expand}$matrix

but until {expand} 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.)


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 {expand} syntax, like this:

   # Instead of: set foo [lconcat $bar $boo $spong]
   set foo [list {expand}$bar {expand}$boo {expand}$spong]

[ Tcl syntax help - Arts and crafts of Tcl-Tk programming - Category Command of Tcl ]