tags:

views:

58

answers:

2

Hello, I'm playing around with Tcl and have found several scenarios where [list a b c] is interchangeable with {a b c}. What is the preferred method, and where does [list a b c] fail to match the behavior of {a b c}?

+6  A: 
% set lista [list a b c]
a b c
% set listb {a b c}
a b c
% set b {1 2 3}
1 2 3
% set lista [list a $b c]
a {1 2 3} c
% set listb {a $b c}
a $b c

When you are building a list using literals, the two forms are equivalent. When you are using variables, the [list ...] form will expand the variable before placing it in the string and the {...} form will not.

Essentially, {...} treats whatever is inside of it as a single, continuous string; the special character $ is never interpreted. The [list ...] statement takes its arguments and concatenates them together, separated by spaces. Therefore, if the items you are working with are string literals and do not contain anything that needs to be interpreted, then the two forms are the same.

bta
maybe worth comparing to 'set list c "a $b c"' as well
jk
+3  A: 

For literals, they're identical in all functional respects (other than that the straight literal form is slightly faster, of course). For non-literals, they're obviously doing different things (as bta says).

However, there's more to it than that. Let's dive deeper!

There are cases where you do not want to use the {…} or the "…" forms, and that's exactly when working with certain non-literals. In particular, if you are using tcom or Tcl/Java (i.e., Jacl or TclBlend) then you will be working with objects that do not obey Tcl's semantics properly. In particular, you'll have “fragile” objects attached to some of the values; if the Tcl_Obj containing the reference to the value has its type changed (“shimmered” in Tcl parlance) then the reference to the underlying COM or Java object will be irretrievably dropped and the garbage collector will delete the object before you're finished with it. Using the [list …] form to build lists (and list operations like lindex to retrieve) will ensure that these fragile internal representations are maintained correctly until you no longer need them.

For normal Tcl values, including those produced by most extension packages, you don't need to worry about this other than to note that using the non-lossy operations is also faster. If you want your code to be quick (who doesn't?) then [list] is your friend even when it is not necessary (which it often is).

The other case you want to pay attention to is when producing callbacks.

Often you want to do callbacks where some values are known at the point when the callback is created, and not otherwise stored in some variable that exists when the callback is executed. (I do this a lot with after, fileevent and trace, but there are lots of places where this is done.) Callback scripts that are created with list (or some other list-producing command) are faster than all the other alternatives because the Tcl script evaluation engine can prove that they have no substitutions and go directly to feeding the list elements into the command dispatcher. This is quite an advantage when you're just passing values to a procedure, which is considered good practice for callbacks.

Donal Fellows