• How do I get an element of a list without it being substituted?

    From Choosechee@choosechee@pm.me to comp.lang.tcl on Wed Mar 18 14:50:35 2026
    From Newsgroup: comp.lang.tcl

    Let's say I have defined a list as follows:
    `set myList {"First\nElement" {Second Element}}`
    If I print this list:
    `chan puts $myList`
    I get:
    `"First\nElement" {Second Element}`
    However, if I were to iterate over the list and print the elements:
    `foreach {element} $myList {chan puts $element}`
    I get:
    ```
    First
    Element
    Second Element
    ```
    The elements have undergone substitution before being returned. In most
    cases, this is desirable, but in my case, I want them to be returned
    exactly as written, like:
    ```
    "First\nElement"
    {Second Element}
    ```
    How can I get an element of a list without it being substituted? I can't
    split the list by whitespace, because single elements that contain
    whitespace will also be split.
    --- Synchronet 3.21d-Linux NewsLink 1.2
  • From Helmut Giese@hgiese@ratiosoft.com to comp.lang.tcl on Wed Mar 18 21:16:47 2026
    From Newsgroup: comp.lang.tcl

    Choosechee <choosechee@pm.me> schrieb:

    Let's say I have defined a list as follows:
    `set myList {"First\nElement" {Second Element}}`
    If I print this list:
    `chan puts $myList`
    I get:
    `"First\nElement" {Second Element}`
    However, if I were to iterate over the list and print the elements:
    `foreach {element} $myList {chan puts $element}`
    I get:
    ```
    First
    Element
    Second Element
    ```
    The elements have undergone substitution before being returned. In most >cases, this is desirable, but in my case, I want them to be returned
    exactly as written, like:
    ```
    "First\nElement"
    {Second Element}
    ```
    How can I get an element of a list without it being substituted? I can't >split the list by whitespace, because single elements that contain >whitespace will also be split.
    Hello,
    by using 'llength'?
    Like (all on one line)
    for {set i 0} {$i < [llength $myList]} {incr i} {puts "$i: [lindex
    $myList $i]"}
    HTH
    Helmut
    --- Synchronet 3.21d-Linux NewsLink 1.2
  • From Rich@rich@example.invalid to comp.lang.tcl on Wed Mar 18 20:32:31 2026
    From Newsgroup: comp.lang.tcl

    Choosechee <choosechee@pm.me> wrote:
    Let's say I have defined a list as follows:
    `set myList {"First\nElement" {Second Element}}`

    You have not defined a list. You have defined a string. It is a
    string that happens to be convertable to a list, but it is not a list.
    Curly braces {} do not mean "a list" (although this is a common misconception).

    If I print this list:
    `chan puts $myList`
    I get:
    `"First\nElement" {Second Element}`

    You did not print a list, you printed a string (it has not undergone conversion to a list yet).

    However, if I were to iterate over the list and print the elements:
    `foreach {element} $myList {chan puts $element}`
    I get:
    ```
    First
    Element
    Second Element
    ```
    The elements have undergone substitution before being returned.

    Yes, now you forced Tcl to convert the string to a list, and the
    conversion from string to list also interpreted the backslashes,
    because of the double quotes you used in the string.

    In most cases, this is desirable, but in my case, I want them to be
    returned exactly as written, like:
    ```
    "First\nElement"
    {Second Element}
    ```
    How can I get an element of a list without it being substituted?

    By properly defining a list at the outset (this is the preferred
    method):

    % set myList [list {First\nElement} {Second Element}]
    {First\nElement} {Second Element}
    % foreach {element} $myList {puts $element}
    First\nElement
    Second Element

    Or, if you insist on attempting to manually use the "list serialization syntax" for strings (note that the documentation says to not do this)
    by defining the string such that the substitutions do not occur:

    % set myList {{First\nElement} {Second Element}}
    {First\nElement} {Second Element}
    % foreach {element} $myList {puts $element}
    First\nElement
    Second Element

    --- Synchronet 3.21d-Linux NewsLink 1.2
  • From pmcc@sysfl@free.fr to comp.lang.tcl on Wed Mar 18 21:34:11 2026
    From Newsgroup: comp.lang.tcl

    Helmut Giese wrote:
    Choosechee <choosechee@pm.me> schrieb:

    Let's say I have defined a list as follows:
    `set myList {"First\nElement" {Second Element}}`
    If I print this list:
    `chan puts $myList`
    I get:
    `"First\nElement" {Second Element}`
    However, if I were to iterate over the list and print the elements:
    `foreach {element} $myList {chan puts $element}`
    I get:
    ```
    First
    Element
    Second Element
    ```
    The elements have undergone substitution before being returned. In most
    cases, this is desirable, but in my case, I want them to be returned
    exactly as written, like:
    ```
    "First\nElement"
    {Second Element}
    ```
    How can I get an element of a list without it being substituted? I can't
    split the list by whitespace, because single elements that contain
    whitespace will also be split.
    Hello,
    by using 'llength'?
    Like (all on one line)
    for {set i 0} {$i < [llength $myList]} {incr i} {puts "$i: [lindex
    $myList $i]"}
    HTH
    Helmut


    Hello,

    Maybe building an explicit list is safer :

    set myList [ list {First\nElement} {Second Element} ]

    foreach element $myList { chan puts $element }

    First\nElement
    Second Element

    or if you collect data in different variables :

    set a {First\nElement}
    set b {Second Element}

    set myList [list $a $b]
    or
    set myList [list $a ]
    lappend myList $b

    foreach e $myList { chan puts $e }

    First\nElement
    Second Element

    note that this will fail :
    set myList $a
    foreach e $myList { chan puts $e }

    First
    Element

    Regards
    Pascal

    --- Synchronet 3.21d-Linux NewsLink 1.2
  • From Choosechee@choosechee@pm.me to comp.lang.tcl on Wed Mar 18 16:31:47 2026
    From Newsgroup: comp.lang.tcl

    On 3/18/26 15:34, pmcc wrote:
    Helmut Giese wrote:
    Choosechee <choosechee@pm.me> schrieb:

    Let's say I have defined a list as follows:
    `set myList {"First\nElement" {Second Element}}`
    If I print this list:
    `chan puts $myList`
    I get:
    `"First\nElement" {Second Element}`
    However, if I were to iterate over the list and print the elements:
    `foreach {element} $myList {chan puts $element}`
    I get:
    ```
    First
    Element
    Second Element
    ```
    The elements have undergone substitution before being returned. In most
    cases, this is desirable, but in my case, I want them to be returned
    exactly as written, like:
    ```
    "First\nElement"
    {Second Element}
    ```
    How can I get an element of a list without it being substituted? I can't >>> split the list by whitespace, because single elements that contain
    whitespace will also be split.
    Hello,
    by using 'llength'?
    Like (all on one line)
    for {set i 0} {$i < [llength $myList]}  {incr i} {puts "$i: [lindex
    $myList $i]"}
    HTH
    Helmut


    Hello,

    Maybe building an explicit list is safer :

    set myList [ list {First\nElement} {Second Element} ]

    foreach element $myList { chan puts $element }

    First\nElement
    Second Element

    or if you collect data in different variables :

    set a {First\nElement}
    set b {Second Element}

    set myList [list $a $b]
    or
    set myList [list $a ]
    lappend  myList $b

    foreach e $myList { chan puts $e }

    First\nElement
    Second Element

    note that this will fail :
    set myList $a
    foreach e $myList { chan puts $e }

    First
    Element

    Regards
    Pascal


    In my actual use case, I'm reading the list from a file that someone
    else could have made, so I can't do this.
    --- Synchronet 3.21d-Linux NewsLink 1.2
  • From Choosechee@choosechee@pm.me to comp.lang.tcl on Wed Mar 18 16:33:53 2026
    From Newsgroup: comp.lang.tcl

    On 3/18/26 15:32, Rich wrote:
    Choosechee <choosechee@pm.me> wrote:
    Let's say I have defined a list as follows:
    `set myList {"First\nElement" {Second Element}}`

    You have not defined a list. You have defined a string. It is a
    string that happens to be convertable to a list, but it is not a list.
    Curly braces {} do not mean "a list" (although this is a common misconception).

    If I print this list:
    `chan puts $myList`
    I get:
    `"First\nElement" {Second Element}`

    You did not print a list, you printed a string (it has not undergone conversion to a list yet).

    However, if I were to iterate over the list and print the elements:
    `foreach {element} $myList {chan puts $element}`
    I get:
    ```
    First
    Element
    Second Element
    ```
    The elements have undergone substitution before being returned.

    Yes, now you forced Tcl to convert the string to a list, and the
    conversion from string to list also interpreted the backslashes,
    because of the double quotes you used in the string.

    In most cases, this is desirable, but in my case, I want them to be
    returned exactly as written, like:
    ```
    "First\nElement"
    {Second Element}
    ```
    How can I get an element of a list without it being substituted?

    By properly defining a list at the outset (this is the preferred
    method):

    % set myList [list {First\nElement} {Second Element}]
    {First\nElement} {Second Element}
    % foreach {element} $myList {puts $element}
    First\nElement
    Second Element

    Or, if you insist on attempting to manually use the "list serialization syntax" for strings (note that the documentation says to not do this)
    by defining the string such that the substitutions do not occur:

    % set myList {{First\nElement} {Second Element}}
    {First\nElement} {Second Element}
    % foreach {element} $myList {puts $element}
    First\nElement
    Second Element


    I am actually reading the list from a file. Is this a bad idea? Should I
    just parse it from scratch?
    --- Synchronet 3.21d-Linux NewsLink 1.2
  • From Choosechee@choosechee@pm.me to comp.lang.tcl on Wed Mar 18 16:34:49 2026
    From Newsgroup: comp.lang.tcl

    On 3/18/26 15:16, Helmut Giese wrote:
    Choosechee <choosechee@pm.me> schrieb:

    Let's say I have defined a list as follows:
    `set myList {"First\nElement" {Second Element}}`
    If I print this list:
    `chan puts $myList`
    I get:
    `"First\nElement" {Second Element}`
    However, if I were to iterate over the list and print the elements:
    `foreach {element} $myList {chan puts $element}`
    I get:
    ```
    First
    Element
    Second Element
    ```
    The elements have undergone substitution before being returned. In most
    cases, this is desirable, but in my case, I want them to be returned
    exactly as written, like:
    ```
    "First\nElement"
    {Second Element}
    ```
    How can I get an element of a list without it being substituted? I can't
    split the list by whitespace, because single elements that contain
    whitespace will also be split.
    Hello,
    by using 'llength'?
    Like (all on one line)
    for {set i 0} {$i < [llength $myList]} {incr i} {puts "$i: [lindex
    $myList $i]"}
    HTH
    Helmut

    lindex still substitutes the elements, so this doesn't help.
    --- Synchronet 3.21d-Linux NewsLink 1.2
  • From Robert Heller@heller@deepsoft.com to comp.lang.tcl on Wed Mar 18 21:35:57 2026
    From Newsgroup: comp.lang.tcl

    At Wed, 18 Mar 2026 14:50:35 -0500 Choosechee <choosechee@pm.me> wrote:

    Let's say I have defined a list as follows:
    `set myList {"First\nElement" {Second Element}}`
    If I print this list:
    `chan puts $myList`
    I get:
    `"First\nElement" {Second Element}`
    However, if I were to iterate over the list and print the elements:
    `foreach {element} $myList {chan puts $element}`
    I get:
    ```
    First
    Element
    Second Element
    ```
    The elements have undergone substitution before being returned. In most cases, this is desirable, but in my case, I want them to be returned
    exactly as written, like:
    ```
    "First\nElement"
    {Second Element}
    ```
    No, the elements have NOT undergone substitution. "\n" when passed to puts it prints a newline. "\n" is just the literal string containing one character, a newline, Nothing is being "substituted" (well, except by the input parser processing string escapes: "... \x ..." ).
    How can I get an element of a list without it being substituted? I can't split the list by whitespace, because single elements that contain
    whitespace will also be split.
    You are going to have to write a version of "puts" that escapes "special" characters (like newline).
    Something like (this assumes 7-bit ASCII -- handline UTF-8 is left as an excerise, but this gives the general idea):
    proc escape-puts {channel string} {
    foreach c [split $string] {
    switch c {
    "\n" {puts -nonewline $channel "\\n"}
    "\r" {puts -nonewline $channel "\\r"}
    "\t" {puts -nonewline $channel "\\t"}
    "\b" {puts -nonewline $channel "\\b"}
    default {
    set char [scan $c "%c"]
    if {$char < 32 || $char == 127} {
    set char [scan $c "%c"]
    puts -nonewline $channel [format {\\%03o} $char]
    } else {
    puts -nonewline $channel $c
    }
    }
    }
    }
    }


    --
    Robert Heller -- Cell: 413-658-7953 GV: 978-633-5364
    Deepwoods Software -- Custom Software Services
    http://www.deepsoft.com/ -- Linux Administration Services
    heller@deepsoft.com -- Webhosting Services
    --- Synchronet 3.21d-Linux NewsLink 1.2
  • From Rich@rich@example.invalid to comp.lang.tcl on Thu Mar 19 02:50:33 2026
    From Newsgroup: comp.lang.tcl

    Choosechee <choosechee@pm.me> wrote:
    On 3/18/26 15:32, Rich wrote:
    Choosechee <choosechee@pm.me> wrote:
    Let's say I have defined a list as follows:
    `set myList {"First\nElement" {Second Element}}`

    You have not defined a list. You have defined a string. It is a
    string that happens to be convertable to a list, but it is not a list.
    Curly braces {} do not mean "a list" (although this is a common
    misconception).

    If I print this list:
    `chan puts $myList`
    I get:
    `"First\nElement" {Second Element}`

    You did not print a list, you printed a string (it has not undergone
    conversion to a list yet).

    However, if I were to iterate over the list and print the elements:
    `foreach {element} $myList {chan puts $element}`
    I get:
    ```
    First
    Element
    Second Element
    ```
    The elements have undergone substitution before being returned.

    Yes, now you forced Tcl to convert the string to a list, and the
    conversion from string to list also interpreted the backslashes,
    because of the double quotes you used in the string.

    In most cases, this is desirable, but in my case, I want them to be
    returned exactly as written, like:
    ```
    "First\nElement"
    {Second Element}
    ```
    How can I get an element of a list without it being substituted?

    By properly defining a list at the outset (this is the preferred
    method):

    % set myList [list {First\nElement} {Second Element}]
    {First\nElement} {Second Element}
    % foreach {element} $myList {puts $element}
    First\nElement
    Second Element

    Or, if you insist on attempting to manually use the "list serialization
    syntax" for strings (note that the documentation says to not do this)
    by defining the string such that the substitutions do not occur:

    % set myList {{First\nElement} {Second Element}}
    {First\nElement} {Second Element}
    % foreach {element} $myList {puts $element}
    First\nElement
    Second Element


    I am actually reading the list from a file. Is this a bad idea?

    We can't read your mind. It is best to tell us these facts as part of the initial posting.

    Whether this is a bad idea depends upon whether you can depend upon the
    string from the file being properly formatted as a list. In a response
    to pmcc you said it was also being created by someone else, which means
    if you use Tcl's default conversion, you are dependent upon someone
    else always correctly formatting the list encoding. If they get a
    single character wrong in just the right place, you'll take an error in
    your code.

    I.e.:

    % set is_it_a_list {a "b c}
    a "b c
    % lindex $is_it_a_list 1
    unmatched open quote in list

    Should I just parse it from scratch?

    If you can't be sure it is always properly encoded as a string that
    Tcl can convert automatically, then yes, it is better to do the parse
    yourself from scratch.
    --- Synchronet 3.21d-Linux NewsLink 1.2
  • From Rich@rich@example.invalid to comp.lang.tcl on Thu Mar 19 02:59:33 2026
    From Newsgroup: comp.lang.tcl

    Robert Heller <heller@deepsoft.com> wrote:
    At Wed, 18 Mar 2026 14:50:35 -0500 Choosechee <choosechee@pm.me> wrote:


    Let's say I have defined a list as follows:
    `set myList {"First\nElement" {Second Element}}`
    If I print this list:
    `chan puts $myList`
    I get:
    `"First\nElement" {Second Element}`
    However, if I were to iterate over the list and print the elements:
    `foreach {element} $myList {chan puts $element}`
    I get:
    ```
    First
    Element
    Second Element
    ```
    The elements have undergone substitution before being returned. In most
    cases, this is desirable, but in my case, I want them to be returned
    exactly as written, like:
    ```
    "First\nElement"
    {Second Element}
    ```

    No, the elements have NOT undergone substitution.

    Are you sure?:

    % set myList {"First\nElement" {Second Element}}
    "First\nElement" {Second Element}
    % llength $myList
    2
    % lindex $myList 0
    First
    Element

    It looks like the list parser, when encountering a quoted string in the
    thing it is parsing to a list, has invoked rule 4 and performed
    "backslash substitution" when creating list element zero.

    A variant example:

    % set myList {"First\nElement" {Second Element}}
    "First\nElement" {Second Element}

    Shimmer to a list

    % llength $myList
    2

    Append one element (in order to destroy the cached "string rep")

    % lappend myList 3
    {First
    Element} {Second Element} 3

    And the \n has been converted into an actual newline.

    --- Synchronet 3.21d-Linux NewsLink 1.2
  • From Choosechee@choosechee@pm.me to comp.lang.tcl on Wed Mar 18 22:22:51 2026
    From Newsgroup: comp.lang.tcl

    On 3/18/26 21:50, Rich wrote:
    Choosechee <choosechee@pm.me> wrote:
    On 3/18/26 15:32, Rich wrote:
    Choosechee <choosechee@pm.me> wrote:
    Let's say I have defined a list as follows:
    `set myList {"First\nElement" {Second Element}}`

    You have not defined a list. You have defined a string. It is a
    string that happens to be convertable to a list, but it is not a list.
    Curly braces {} do not mean "a list" (although this is a common
    misconception).

    If I print this list:
    `chan puts $myList`
    I get:
    `"First\nElement" {Second Element}`

    You did not print a list, you printed a string (it has not undergone
    conversion to a list yet).

    However, if I were to iterate over the list and print the elements:
    `foreach {element} $myList {chan puts $element}`
    I get:
    ```
    First
    Element
    Second Element
    ```
    The elements have undergone substitution before being returned.

    Yes, now you forced Tcl to convert the string to a list, and the
    conversion from string to list also interpreted the backslashes,
    because of the double quotes you used in the string.

    In most cases, this is desirable, but in my case, I want them to be
    returned exactly as written, like:
    ```
    "First\nElement"
    {Second Element}
    ```
    How can I get an element of a list without it being substituted?

    By properly defining a list at the outset (this is the preferred
    method):

    % set myList [list {First\nElement} {Second Element}]
    {First\nElement} {Second Element}
    % foreach {element} $myList {puts $element}
    First\nElement
    Second Element

    Or, if you insist on attempting to manually use the "list serialization
    syntax" for strings (note that the documentation says to not do this)
    by defining the string such that the substitutions do not occur:

    % set myList {{First\nElement} {Second Element}}
    {First\nElement} {Second Element}
    % foreach {element} $myList {puts $element}
    First\nElement
    Second Element


    I am actually reading the list from a file. Is this a bad idea?

    We can't read your mind. It is best to tell us these facts as part of the initial posting.

    Whether this is a bad idea depends upon whether you can depend upon the string from the file being properly formatted as a list. In a response
    to pmcc you said it was also being created by someone else, which means
    if you use Tcl's default conversion, you are dependent upon someone
    else always correctly formatting the list encoding. If they get a
    single character wrong in just the right place, you'll take an error in
    your code.

    I.e.:

    % set is_it_a_list {a "b c}
    a "b c
    % lindex $is_it_a_list 1
    unmatched open quote in list

    Should I just parse it from scratch?

    If you can't be sure it is always properly encoded as a string that
    Tcl can convert automatically, then yes, it is better to do the parse yourself from scratch.

    Sorry, I do need to learn to be more specific when asking questions like
    this. Anyways, I'm okay with having a fail state, so couldn't I just
    check with `string is list $myList` and throw my own error if it returns 0?
    --- Synchronet 3.21d-Linux NewsLink 1.2
  • From Choosechee@choosechee@pm.me to comp.lang.tcl on Wed Mar 18 22:28:33 2026
    From Newsgroup: comp.lang.tcl

    On 3/18/26 14:50, Choosechee wrote:
    Let's say I have defined a list as follows:
    `set myList {"First\nElement" {Second Element}}`
    If I print this list:
    `chan puts $myList`
    I get:
    `"First\nElement" {Second Element}`
    However, if I were to iterate over the list and print the elements:
    `foreach {element} $myList {chan puts $element}`
    I get:
    ```
    First
    Element
    Second Element
    ```
    The elements have undergone substitution before being returned. In most cases, this is desirable, but in my case, I want them to be returned
    exactly as written, like:
    ```
    "First\nElement"
    {Second Element}
    ```
    How can I get an element of a list without it being substituted? I can't split the list by whitespace, because single elements that contain whitespace will also be split.
    Okay, well, I created some code to brace every element before I use the
    list. This won't prevent a \ followed by a new line from becoming a
    space, but this is actually okay for my use case. Here's my code if you
    want it:
    ```
    set WHITESPACE(\t) 1
    set WHITESPACE(\n) 1
    set WHITESPACE(\v) 1
    set WHITESPACE(\f) 1
    set WHITESPACE(\r) 1
    set WHITESPACE(\ ) 1
    array default set WHITESPACE 0

    const WHITESPACE_REGEX "\[[join [array names WHITESPACE]]\]"
    const UNSURROUNDED_STRING_END_REGEX [string cat {[^\\](?:\\\\)*} ($WHITESPACE_REGEX|\$)]
    # Parenthesized quotation is concatenated because my editor highlighting
    is bad
    const QUOTED_STRING_END_REGEX [string cat {[^\\](?:\\\\)*} (\")]

    proc braceListElements {listStr} {
    global WHITESPACE
    set i 0

    while {$i < [string length $listStr]} {
    while {$WHITESPACE([string index $listStr $i])} {
    incr i
    }

    if {$i >= [string length $listStr]} {
    break
    }

    set tokenStartIndex $i
    set firstTokenChar [string index $listStr $tokenStartIndex]

    set token [switch $firstTokenChar {
    "\"" {GetQuotedStringToken $listStr i}
    "\{" {GetBracedStringToken $listStr i}
    default {GetUnsurroundedStringToken $listStr i}
    }]
    set tokenEndIndex $i

    set listStr [string replace $listStr $tokenStartIndex $tokenEndIndex
    "{$token}"]
    incr i 3
    }

    return $listStr
    }

    proc GetUnsurroundedStringToken {listStr iVar} {
    global UNSURROUNDED_STRING_END_REGEX
    upvar $iVar i
    set tokenStartIndex $i

    set tokenEndIndex {}
    if {[regexp -indices -start $i $UNSURROUNDED_STRING_END_REGEX $listStr _ tokenEndIndex]} {
    set tokenEndIndex [expr {[lindex $tokenEndIndex 0] - 1}]
    } else {
    error "String ends with substitute-disabling \\"
    }

    set i $tokenEndIndex
    return [string range $listStr $tokenStartIndex $tokenEndIndex]
    }

    proc GetQuotedStringToken {listStr iVar} {
    global QUOTED_STRING_END_REGEX
    upvar $iVar i
    set tokenStartIndex $i

    set tokenEndIndex {}
    if {[regexp -indices -start $i $QUOTED_STRING_END_REGEX $listStr _ tokenEndIndex]} {
    set tokenEndIndex [lindex $tokenEndIndex 0]
    } else {
    error "Unclosed quoted string starting at index $tokenStartIndex."
    }

    set i $tokenEndIndex
    return [string range $listStr $tokenStartIndex $tokenEndIndex]
    }

    proc GetBracedStringToken {listStr iVar} {
    upvar $iVar i
    set tokenStartIndex $i
    set unclosedBraces 1
    set isEscaping false

    for {incr i} {$i < [string length $listStr]} {incr i} {
    if {$isEscaping} {
    set isEscaping false
    continue
    }

    set currentChar [string index $listStr $i]
    switch $currentChar {
    "\{" {incr unclosedBraces}
    "\}" {incr unclosedBraces -1}
    "\\" {set isEscaping true}
    }

    if {$unclosedBraces == 0} {
    break
    }
    }

    if {$unclosedBraces > 0} {
    error "Unclosed braced string starting at index $tokenStartIndex"
    }

    set tokenEndIndex $i
    return [string range $listStr $tokenStartIndex $tokenEndIndex]
    }
    ```
    --- Synchronet 3.21d-Linux NewsLink 1.2
  • From Rich@rich@example.invalid to comp.lang.tcl on Thu Mar 19 03:55:37 2026
    From Newsgroup: comp.lang.tcl

    Choosechee <choosechee@pm.me> wrote:
    On 3/18/26 21:50, Rich wrote:
    Choosechee <choosechee@pm.me> wrote:
    I am actually reading the list from a file. Is this a bad idea?

    We can't read your mind. It is best to tell us these facts as part
    of the initial posting.

    Whether this is a bad idea depends upon whether you can depend upon
    the string from the file being properly formatted as a list. In a
    response to pmcc you said it was also being created by someone else,
    which means if you use Tcl's default conversion, you are dependent
    upon someone else always correctly formatting the list encoding. If
    they get a single character wrong in just the right place, you'll
    take an error in your code.

    I.e.:

    % set is_it_a_list {a "b c}
    a "b c
    % lindex $is_it_a_list 1
    unmatched open quote in list

    Should I just parse it from scratch?

    If you can't be sure it is always properly encoded as a string that
    Tcl can convert automatically, then yes, it is better to do the
    parse yourself from scratch.

    Sorry, I do need to learn to be more specific when asking questions
    like this. Anyways, I'm okay with having a fail state, so couldn't I
    just check with `string is list $myList` and throw my own error if it returns 0?

    Yes, that is a perfectly reasonable way to check if the string is
    properly formatted. And it also lets you handle the error instead of
    having your script terminate.
    --- Synchronet 3.21d-Linux NewsLink 1.2
  • From Ralf Fassel@ralfixx@gmx.de to comp.lang.tcl on Thu Mar 19 11:11:05 2026
    From Newsgroup: comp.lang.tcl

    * Choosechee <choosechee@pm.me>
    | Okay, well, I created some code to brace every element before I use
    | the list. This won't prevent a \ followed by a new line from becoming
    | a space, but this is actually okay for my use case. Here's my code if
    | you want it:

    That looks like an awful amount of code to achieve something which
    breaks nevertheless in corner cases. Manually bracing list elements
    instead of letting TCL itself do the job is never a good idea IMHO.

    If you read data from an external source, and you cannot be sure about
    it being properly 'listified', then indeed [string is list] (or
    [info complete] in case of multi-line lists) would be the way to go.

    Or just 'split' the file contents by whitespace and use the resulting
    list (line orientation assumed for simplicity):

    set line [gets $fd]
    # eg line => some "unbalanced { tcl control ] not a \n newline
    set list [split $line]
    # list => some {"unbalanced} \{ tcl control \] not a {\n} newline

    This way everything is properly quoted w/o big magic.

    foreach elt $list { puts "elt {$elt}" }
    elt {some}
    elt {"unbalanced}
    elt {{}
    elt {tcl}
    elt {control}
    elt {]}
    elt {not}
    elt {a}
    elt {\n}
    elt {newline}


    HTH
    R'
    --- Synchronet 3.21d-Linux NewsLink 1.2
  • From Emiliano@emiliano@example.invalid to comp.lang.tcl on Thu Mar 19 18:08:07 2026
    From Newsgroup: comp.lang.tcl

    On Thu, 19 Mar 2026 02:59:33 -0000 (UTC)
    Rich <rich@example.invalid> wrote:

    [...]
    Are you sure?:

    % set myList {"First\nElement" {Second Element}}
    "First\nElement" {Second Element}
    % llength $myList
    2
    % lindex $myList 0
    First
    Element

    It looks like the list parser, when encountering a quoted string in the thing it is parsing to a list, has invoked rule 4 and performed
    "backslash substitution" when creating list element zero.

    Yes, this is described in detail in TIP 407 "The String Representation
    of Tcl Lists: the Gory Details".

    https://core.tcl-lang.org/tips/doc/trunk/tip/407.md

    Regards
    --
    Emiliano <emil.gavilan@gmail.com>
    --- Synchronet 3.21d-Linux NewsLink 1.2
  • From Christian Gollwitzer@auriocus@gmx.de to comp.lang.tcl on Fri Mar 20 08:09:56 2026
    From Newsgroup: comp.lang.tcl

    Am 18.03.26 um 20:50 schrieb Choosechee:
    Let's say I have defined a list as follows:
    [...]
    The elements have undergone substitution before being returned. In most cases, this is desirable, but in my case, I want them to be returned
    exactly as written, like:
    ```
    "First\nElement"
    {Second Element}
    ```
    How can I get an element of a list without it being substituted?

    It appears to me, that what you say - I want to extract list arguments
    with quoting - and what you really want, are two different things.

    Reading the whole discussion I get the impression that your main
    motivation is to have a human-readable configuration file, and you seek
    a way to parse it, but Tcl's list-parser doesn't do the job.

    I would advise to either
    a) define your format thoroughly, this is harder than you might think,
    and write your own parser that does it from the string
    b) use one of the established formats that the external users know, such
    as JSON or YAML, and then use an existing parser for that (rl-json,
    tcldom, ...)

    In all but the simplest cases I would strongly suggest to go for option
    b), because these formats have been reality-tested for all the edge
    cases. i.e. you can represent any possible string, your users might be
    already familiar with these formats and you can refer to the standard
    for a description.


    Christian
    --- Synchronet 3.21d-Linux NewsLink 1.2
  • From Tristan Wibberley@tristan.wibberley+netnews2@alumni.manchester.ac.uk to comp.lang.tcl on Sat Mar 21 06:39:31 2026
    From Newsgroup: comp.lang.tcl

    On 18/03/2026 20:32, Rich wrote:
    Choosechee <choosechee@pm.me> wrote:
    Let's say I have defined a list as follows:
    `set myList {"First\nElement" {Second Element}}`

    You have not defined a list. You have defined a string. It is a
    string that happens to be convertable to a list, but it is not a list. Curly braces {} do not mean "a list" (although this is a common misconception).

    It /is/ a "list". It is documented in the man pages no less - though I
    can't find the one right now, it was on this computer which hasn't had
    the man pages updated since I saw it last.

    It might not be a "Tcl list" or a "Scheme list" but Choosechee only said "list", which in Tcl is just any thing with a string representation that follows the documented form.
    --
    Tristan Wibberley

    The message body is Copyright (C) 2026 Tristan Wibberley except
    citations and quotations noted. All Rights Reserved except that you may,
    of course, cite it academically giving credit to me, distribute it
    verbatim as part of a usenet system or its archives, and use it to
    promote my greatness and general superiority without misrepresentation
    of my opinions other than my opinion of my greatness and general
    superiority which you _may_ misrepresent. You definitely MAY NOT train
    any production AI system with it but you may train experimental AI that
    will only be used for evaluation of the AI methods it implements.

    --- Synchronet 3.21d-Linux NewsLink 1.2