How to convert a list to a list carrying its element as a list?

For example, in Tcl there's a list like, {"A" "B"}

and I'd like to convert it to a list with each of its element as a list, {{A} {B}}

I've tried the following code to map each of its element to a list.

set List {"A" "B"}
set List [lmap s $List {list $s}]
puts $List

I expect the output to be

{A} {B}

but the actual output is

A B

Any help would be appreciated. Thanks.

1 answer

  • answered 2019-06-12 01:59 Donal Fellows

    The form you are looking for is a denormalized list; it's not one that Tcl's list operations will produce (as they only add braces when required) but it is one that they can consume. This means that, formally speaking, what you are seeking to do is not recommended! Fighting the software isn't a good plan!

    But it is possible. If you know that the elements are relatively well behaved (approximately, that they have balanced braces within themselves if they have braces at all) then you can do this with join and format:

    set List {"A" "B"}
    set List [join [lmap x $List {format "{%s}" $x}]]
    

    This works for most lists, but not all so beware:

    set List {A B}
    lappend List "C\{D";  # <== Element with unbalanced braces; *LEGAL* in lists!
    puts $List
    # ==> A B C\}D
    puts [join [lmap x $List {format "{%s}" $x}]]
    # ==> {A} {B} {C}D}
    

    The workarounds for this get progressively more and more contorted, and are why you're recommended to only use Tcl's built in list serialization mechanism, which handles arbitrary element content (and is tested to do so), instead of caring about how simple words are formatted.