• Subject: TIP 672 Prototype: $(expr) syntax is working!

    From et99@et99@rocketship1.me to comp.lang.tcl on Fri Oct 17 15:23:38 2025
    From Newsgroup: comp.lang.tcl

    I've implemented a working prototype of TIP 672 - the $(expression) syntax for Tcl.

    Instead of:
    set result [expr {$a + $b * $c}]
    puts "Total: [expr {$sum + $tax}]"

    You can now write:
    set result $($a + $b * $c)
    puts "Total: $($sum + $tax)"

    It compiles to identical bytecode as [expr {...}], so there's no performance penalty. Works great in strings, procs, and interactive mode.

    Repository with code and examples in the readme (with details about the new code):

    https://github.com/rocketship88/tcl-tip-672-prototype

    The code is based on Tcl 9.1 source from last week, so the modified files should drop into current builds without conflicts to easily test this prototype.

    The implementation is surprisingly simple - about 100 lines across two files in tclParse.c and tclNamesp.c. It creates a synthetic [expr {...}] string that the existing compiler optimizes normally.

    One limitation: the synthetic strings leak memory (need core team input on the cleanup mechanism). Otherwise it's been working well in testing.

    Thoughts? Does anyone see issues I haven't considered?

    -et99

    --- Synchronet 3.21a-Linux NewsLink 1.2
  • From Rich@rich@example.invalid to comp.lang.tcl on Sat Oct 18 02:48:08 2025
    From Newsgroup: comp.lang.tcl

    et99 <et99@rocketship1.me> wrote:
    I've implemented a working prototype of TIP 672 - the $(expression) syntax for Tcl.

    Instead of:
    set result [expr {$a + $b * $c}]
    puts "Total: [expr {$sum + $tax}]"

    You can now write:
    set result $($a + $b * $c)
    puts "Total: $($sum + $tax)"

    ...

    Thoughts? Does anyone see issues I haven't considered?

    It conflicts with "empty string array names":

    $ rlwrap tclsh
    % set tcl_patchLevel
    8.6.12
    % array set "" [list a 1 b 2 c 4]
    % array get ""
    a 1 b 2 c 4
    % puts $(c)
    4
    % puts $(a)
    1
    %

    Now, naming an array "" is not commonly done, but I've used it (empty
    string) sometimes for the destination array for ::cmdline::getopt and
    friends for storing command line argument options.

    --- Synchronet 3.21a-Linux NewsLink 1.2
  • From Rich@rich@example.invalid to comp.lang.tcl on Sat Oct 18 02:51:11 2025
    From Newsgroup: comp.lang.tcl

    Rich <rich@example.invalid> wrote:
    et99 <et99@rocketship1.me> wrote:
    I've implemented a working prototype of TIP 672 - the $(expression) syntax for Tcl.

    Instead of:
    set result [expr {$a + $b * $c}]
    puts "Total: [expr {$sum + $tax}]"

    You can now write:
    set result $($a + $b * $c)
    puts "Total: $($sum + $tax)"

    ...

    Thoughts? Does anyone see issues I haven't considered?

    It conflicts with "empty string array names":

    $ rlwrap tclsh
    % set tcl_patchLevel
    8.6.12
    % array set "" [list a 1 b 2 c 4]
    % array get ""
    a 1 b 2 c 4
    % puts $(c)
    4
    % puts $(a)
    1
    %

    Now, naming an array "" is not commonly done, but I've used it (empty string) sometimes for the destination array for ::cmdline::getopt and friends for storing command line argument options.

    Just noticed that the "Tcl" manpage explicitly defines empty string as
    a valid array name (emphasis added below):

    Rule #8:

    $name(index) Name gives the name of an array variable and index
    gives the name of an element within that array. Name
    must contain only letters, digits, underscores, and
    namespace separators, and **may be an empty string**.

    --- Synchronet 3.21a-Linux NewsLink 1.2
  • From et99@et99@rocketship1.me to comp.lang.tcl on Fri Oct 17 23:04:51 2025
    From Newsgroup: comp.lang.tcl

    On 10/17/2025 7:51 PM, Rich wrote:
    Rich <rich@example.invalid> wrote:
    et99 <et99@rocketship1.me> wrote:
    I've implemented a working prototype of TIP 672 - the $(expression) syntax for Tcl.

    Instead of:
    set result [expr {$a + $b * $c}]
    puts "Total: [expr {$sum + $tax}]"

    You can now write:
    set result $($a + $b * $c)
    puts "Total: $($sum + $tax)"

    ...

    Thoughts? Does anyone see issues I haven't considered?

    It conflicts with "empty string array names":

    $ rlwrap tclsh
    % set tcl_patchLevel
    8.6.12
    % array set "" [list a 1 b 2 c 4]
    % array get ""
    a 1 b 2 c 4
    % puts $(c)
    4
    % puts $(a)
    1
    %

    Now, naming an array "" is not commonly done, but I've used it (empty
    string) sometimes for the destination array for ::cmdline::getopt and
    friends for storing command line argument options.

    Just noticed that the "Tcl" manpage explicitly defines empty string as
    a valid array name (emphasis added below):

    Rule #8:

    $name(index) Name gives the name of an array variable and index
    gives the name of an element within that array. Name
    must contain only letters, digits, underscores, and
    namespace separators, and **may be an empty string**.



    Yes, this is expressly documented in the readme at the repository as well as the TIP.

    This is only targeted for version 9.1 and later. I see I did forget to explicitly mention that in my post. As with other 9.x new features, some incompatibilities will arise.

    However, please note, this TIP does not preclude using an invisible name for an array, however, it does require that anyone who uses this (likely rare) construct would have to change over to one of two approaches to read the array (writing it still will work).

    One by simply using {}'s

    ${(index)}

    the other with a command

    [set (index)]

    statement.

    This TIP was written to solve two issues with [expr]. if you look at the second reason mentioned in the TIP: that it improves security, I think you might find it a useful change for the 9.x system, given that only a minor change to coding would be required if one really still wants to use the array with no name.

    Also, this TIP has no sponsor and has not been voted on. I am simply telling the tcl world that they can experiment (find bugs, express opinions on its implementation etc., tell me it's an awful idea) and otherwise play around with the change. Until now, one had to use JimTcl to test out this feature. Now it works in the very latest 9.1 Tcl.

    -et99

    --- Synchronet 3.21a-Linux NewsLink 1.2
  • From Mark Summerfield@m.n.summerfield@gmail.com to comp.lang.tcl on Sat Oct 18 07:18:02 2025
    From Newsgroup: comp.lang.tcl

    On Fri, 17 Oct 2025 23:04:51 -0700, et99 wrote:

    On 10/17/2025 7:51 PM, Rich wrote:
    Rich <rich@example.invalid> wrote:
    et99 <et99@rocketship1.me> wrote:
    I've implemented a working prototype of TIP 672 - the $(expression) syntax for Tcl.

    Instead of:
    set result [expr {$a + $b * $c}]
    puts "Total: [expr {$sum + $tax}]"

    You can now write:
    set result $($a + $b * $c)
    puts "Total: $($sum + $tax)"

    ...

    Thoughts? Does anyone see issues I haven't considered?
    [snip]
    This TIP was written to solve two issues with [expr]. if you look at the second reason mentioned in the TIP: that it improves security, I think you might find it a useful change for the 9.x system, given that only a minor change to coding would be required if one really still wants to use the array with no name.

    Also, this TIP has no sponsor and has not been voted on. I am simply telling the tcl world that they can experiment (find bugs, express opinions on its implementation etc., tell me it's an awful idea) and otherwise play around with the change. Until now, one had to use JimTcl to test out this feature. Now it works in the very latest 9.1 Tcl.

    -et99

    As an ordinary user I find this new syntax very appealing
    and I hope it is adopted.

    (Bikeshedding: regarding the parentheses, given that they
    conflict with array syntax (in one rare case?) would an
    alternative pair of delimiters work? For example:

    set result $<$a + $b * $c>
    puts "Total: $<$sum + $tax>"

    Although presumably this would conflict with variable `$<`
    which I suppose a Tcl refugee from Perl might use.)
    --- Synchronet 3.21a-Linux NewsLink 1.2
  • From et99@et99@rocketship1.me to comp.lang.tcl on Sat Oct 18 01:20:08 2025
    From Newsgroup: comp.lang.tcl

    On 10/18/2025 12:18 AM, Mark Summerfield wrote:
    On Fri, 17 Oct 2025 23:04:51 -0700, et99 wrote:

    On 10/17/2025 7:51 PM, Rich wrote:
    Rich <rich@example.invalid> wrote:
    et99 <et99@rocketship1.me> wrote:
    I've implemented a working prototype of TIP 672 - the $(expression) syntax for Tcl.

    Instead of:
    set result [expr {$a + $b * $c}]
    puts "Total: [expr {$sum + $tax}]"

    You can now write:
    set result $($a + $b * $c)
    puts "Total: $($sum + $tax)"

    ...

    [snip]


    As an ordinary user I find this new syntax very appealing
    and I hope it is adopted.

    (Bikeshedding: regarding the parentheses, given that they
    conflict with array syntax (in one rare case?) would an
    alternative pair of delimiters work? For example:

    set result $<$a + $b * $c>
    puts "Total: $<$sum + $tax>"

    Although presumably this would conflict with variable `$<`
    which I suppose a Tcl refugee from Perl might use.)


    Thanks for the positive feedback!

    Regarding alternative delimiters - parentheses were chosen for several reasons:

    1. Jim Tcl precedent - They've used $(...) successfully for years, proving it works in practice

    2. Limited options - Tcl already uses [] for command substitution and {} for grouping/quoting. That leaves only <> and () as symmetrical ascii paired delimiters (using `' would seem odd).

    3. Avoids escaping problems - Using <> would require escaping comparison operators:

    $<$a \<= $b> # Need to escape <=, >=, <, >
    $($a <= $b) # No escaping needed

    4. Natural pairing - Parentheses nest and balance automatically, which is crucial for complex expressions

    5. Common in expressions - Every language uses () for grouping: $(($a + $b) * $c) reads naturally

    The empty array name conflict is real but extremely rare, and easily worked around with ${(index)} or [set (index)] when needed.

    It's also worth noting that Tcl already has special-case code to handle empty array names - they're not a natural part of the array syntax. This suggests they were always an edge case rather than a core feature. Moving forward with $(...) in Tcl 9.x could actually simplify the parser by removing one special case while adding a more useful feature.

    --et99

    --- Synchronet 3.21a-Linux NewsLink 1.2
  • From Mark Summerfield@m.n.summerfield@gmail.com to comp.lang.tcl on Sat Oct 18 09:11:12 2025
    From Newsgroup: comp.lang.tcl

    On Sat, 18 Oct 2025 01:20:08 -0700, et99 wrote:

    On 10/18/2025 12:18 AM, Mark Summerfield wrote:
    On Fri, 17 Oct 2025 23:04:51 -0700, et99 wrote:

    On 10/17/2025 7:51 PM, Rich wrote:
    Rich <rich@example.invalid> wrote:
    et99 <et99@rocketship1.me> wrote:
    I've implemented a working prototype of TIP 672 - the $(expression) syntax for Tcl.

    Instead of:
    set result [expr {$a + $b * $c}]
    puts "Total: [expr {$sum + $tax}]"

    You can now write:
    set result $($a + $b * $c)
    puts "Total: $($sum + $tax)"

    ...

    [snip]


    As an ordinary user I find this new syntax very appealing
    and I hope it is adopted.

    (Bikeshedding: regarding the parentheses, given that they
    conflict with array syntax (in one rare case?) would an
    alternative pair of delimiters work? For example:

    set result $<$a + $b * $c>
    puts "Total: $<$sum + $tax>"

    Although presumably this would conflict with variable `$<`
    which I suppose a Tcl refugee from Perl might use.)


    Thanks for the positive feedback!

    Regarding alternative delimiters - parentheses were chosen for several reasons:

    1. Jim Tcl precedent - They've used $(...) successfully for years, proving it works in practice

    2. Limited options - Tcl already uses [] for command substitution and {} for grouping/quoting. That leaves only <> and () as symmetrical ascii paired delimiters (using `' would seem odd).

    3. Avoids escaping problems - Using <> would require escaping comparison operators:

    $<$a \<= $b> # Need to escape <=, >=, <, >
    $($a <= $b) # No escaping needed

    4. Natural pairing - Parentheses nest and balance automatically, which is crucial for complex expressions

    5. Common in expressions - Every language uses () for grouping: $(($a + $b) * $c) reads naturally

    The empty array name conflict is real but extremely rare, and easily worked around with ${(index)} or [set (index)] when needed.

    It's also worth noting that Tcl already has special-case code to handle empty array names - they're not a natural part of the array syntax. This suggests they were always an edge case rather than a core feature. Moving forward with $(...) in Tcl 9.x could actually simplify the parser by removing one special case while adding a more useful feature.

    --et99

    Thanks for the explanation. I really hope the `$(...)` syntax is adopted.
    --- Synchronet 3.21a-Linux NewsLink 1.2
  • From Colin Macleod@user7@newsgrouper.org.invalid to comp.lang.tcl on Sat Oct 18 11:30:48 2025
    From Newsgroup: comp.lang.tcl

    et99 <et99@rocketship1.me> posted:

    I've implemented a working prototype of TIP 672 - the $(expression)
    syntax for Tcl.

    Implementing this would make my TIP 676 redundant, but I wouldn't shed
    any tears for that: https://core.tcl-lang.org/tips/doc/trunk/tip/676.md
    This notation is more compact and has a simpler implementation than mine.

    I do like the idea of having {*}{expression} as one instance of a
    generalised expansion system as proposed in https://wiki.tcl-lang.org/page/Expanding+the+Expansion+Prefix
    but perhaps that's too radical.

    I certainly agree that a streamlined expression syntax would eliminate
    one of the biggest warts that tends to put people off Tcl.
    --
    Colin Macleod ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ https://cmacleod.me.uk

    FEED FEED FEED FEED FEED FEED FEED FEED
    GAZA GAZA GAZA GAZA GAZA GAZA GAZA GAZA
    NOW! NOW! NOW! NOW! NOW! NOW! NOW! NOW!
    --- Synchronet 3.21a-Linux NewsLink 1.2
  • From Colin Macleod@user7@newsgrouper.org.invalid to comp.lang.tcl on Sat Oct 18 11:32:19 2025
    From Newsgroup: comp.lang.tcl

    Colin Macleod <user7@newsgrouper.org.invalid> posted:

    I do like the idea of having {*}{expression} as one instance of a
    generalised expansion system as proposed in https://wiki.tcl-lang.org/page/Expanding+the+Expansion+Prefix
    but perhaps that's too radical.

    Correction, I meant to write {=}{expression} Doh!
    --
    Colin Macleod ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ https://cmacleod.me.uk

    FEED FEED FEED FEED FEED FEED FEED FEED
    GAZA GAZA GAZA GAZA GAZA GAZA GAZA GAZA
    NOW! NOW! NOW! NOW! NOW! NOW! NOW! NOW!
    --- Synchronet 3.21a-Linux NewsLink 1.2
  • From et99@et99@rocketship1.me to comp.lang.tcl on Sat Oct 18 07:14:22 2025
    From Newsgroup: comp.lang.tcl

    On 10/18/2025 4:30 AM, Colin Macleod wrote:
    et99 <et99@rocketship1.me> posted:

    I've implemented a working prototype of TIP 672 - the $(expression)
    syntax for Tcl.

    Implementing this would make my TIP 676 redundant, but I wouldn't shed
    any tears for that: https://core.tcl-lang.org/tips/doc/trunk/tip/676.md
    This notation is more compact and has a simpler implementation than mine.

    I do like the idea of having {*}{expression} as one instance of a
    generalised expansion system as proposed in https://wiki.tcl-lang.org/page/Expanding+the+Expansion+Prefix
    but perhaps that's too radical.

    I certainly agree that a streamlined expression syntax would eliminate
    one of the biggest warts that tends to put people off Tcl.



    Thank you for the support and for your willingness to consolidate efforts! It's encouraging to see convergence around addressing this long-standing issue.

    There have been many ideas over the decades for improving Tcl expressions. I too had a previous method, similar to $(...) but without the $ and only working when () were the first and last characters of a tcl word, like how {...} works.

    That approach had limitations - it wouldn't work inside quoted strings or as part of index expressions. But $(...) handles both:

    set text [string range $string 0 end-$($z+1)]

    puts "sum = $($a+$b)"

    And it's been tested for years in JimTcl.

    The security and performance benefits are crucial. If this was just syntactic sugar, it wouldn't have a chance with the TCT. But $(...) ensures all [expr] use - via this shortcut - will have but a single braced argument - as safe and performant as possible without major surgery.

    I collaborated with heinrichmartin (comp.lang.tcl, 2018-19) who invented the synthetic command token mechanism that makes this work in only ~100 lines of code. So I've adopted JimTcl's syntax with heinrichmartin's implementation technique.

    Thanks to both JimTcl and heinrichmartin for the foundational work.

    --et99

    --- Synchronet 3.21a-Linux NewsLink 1.2
  • From Jonathan Kelly@jonkelly@fastmail.fm to comp.lang.tcl on Sun Oct 19 08:47:53 2025
    From Newsgroup: comp.lang.tcl

    On 18/10/25 09:23, et99 wrote:
    I've implemented a working prototype of TIP 672 - the $(expression)
    syntax for Tcl.

    Instead of:
      set result [expr {$a + $b * $c}]
      puts "Total: [expr {$sum + $tax}]"

    You can now write:
      set result $($a + $b * $c)
      puts "Total: $($sum + $tax)"

    It compiles to identical bytecode as [expr {...}], so there's no
    performance penalty. Works great in strings, procs, and interactive mode.

    Repository with code and examples in the readme (with details about the
    new code):

    https://github.com/rocketship88/tcl-tip-672-prototype

    The code is based on Tcl 9.1 source from last week, so the modified
    files should drop into current builds without conflicts to easily test
    this prototype.

    The implementation is surprisingly simple - about 100 lines across two
    files in tclParse.c and tclNamesp.c. It creates a synthetic [expr {...}] string that the existing compiler optimizes normally.

    One limitation: the synthetic strings leak memory (need core team input
    on the cleanup mechanism). Otherwise it's been working well in testing.

    Thoughts? Does anyone see issues I haven't considered?

    -et99

    Oh yes, I love that. I've been sticking to 8.6 on our work servers,
    because if it ain't broke ... but I'd definitely upgrade to 9 for that
    alone.

    Do general users get a chance to vote, if this is at a voteable stage?

    Jonathan.

    --- Synchronet 3.21a-Linux NewsLink 1.2
  • From et99@et99@rocketship1.me to comp.lang.tcl on Sat Oct 18 15:18:50 2025
    From Newsgroup: comp.lang.tcl

    On 10/18/2025 2:47 PM, Jonathan Kelly wrote:
    On 18/10/25 09:23, et99 wrote:
    I've implemented a working prototype of TIP 672 - the $(expression) syntax for Tcl.

    Instead of:
       set result [expr {$a + $b * $c}]
       puts "Total: [expr {$sum + $tax}]"

    You can now write:
       set result $($a + $b * $c)
       puts "Total: $($sum + $tax)"

    It compiles to identical bytecode as [expr {...}], so there's no performance penalty. Works great in strings, procs, and interactive mode.

    Repository with code and examples in the readme (with details about the new code):

    https://github.com/rocketship88/tcl-tip-672-prototype

    The code is based on Tcl 9.1 source from last week, so the modified files should drop into current builds without conflicts to easily test this prototype.

    The implementation is surprisingly simple - about 100 lines across two files in tclParse.c and tclNamesp.c. It creates a synthetic [expr {...}] string that the existing compiler optimizes normally.

    One limitation: the synthetic strings leak memory (need core team input on the cleanup mechanism). Otherwise it's been working well in testing.

    Thoughts? Does anyone see issues I haven't considered?

    -et99

    Oh yes, I love that. I've been sticking to 8.6 on our work servers, because if it ain't broke ... but I'd definitely upgrade to 9 for that alone.

    Do general users get a chance to vote, if this is at a voteable stage?

    Jonathan.


    Thanks for the enthusiastic support!

    Currently, TIP 672 doesn't have a sponsor yet, which is required before it can move to a vote. However, there's positive interest from the core team, and it may be discussed in their next biweekly telco on Monday.

    General users (you and me) don't vote on TIPs directly - the Tcl Core Team makes those decisions. However, community feedback like yours is valuable and does influence the discussion. Expressing support on comp.lang.tcl and the mailing lists helps show there's genuine user demand for the feature.

    The working prototype is available now if you want to experiment with it:

    https://github.com/rocketship88/tcl-tip-672-prototype

    Since the code is a derivative of the latest 9.1 code (9.1a1) within the last 5 days, if you know how to build from sources, all you'd need to do is replace the two files (tclParse.c and tclNamesp.c) in the generic folder, with those 2 in the repository. No need to worry about using diff's etc. Then just build into a temporary folder.

    (I'm on windows, so I have batch scripts to do that including builds with symbols so I can debug with visual studio 2022, which is a truly superb tool.)

    Your feedback on real-world usage would be helpful as the discussion moves forward!

    --et99

    --- Synchronet 3.21a-Linux NewsLink 1.2
  • From saito@saitology9@gmail.com to comp.lang.tcl on Sun Oct 19 15:28:44 2025
    From Newsgroup: comp.lang.tcl

    On 10/17/2025 10:48 PM, Rich wrote:

    Thoughts? Does anyone see issues I haven't considered?

    It conflicts with "empty string array names":

    ...
    Now, naming an array "" is not commonly done, but I've used it (empty
    string) sometimes for the destination array for ::cmdline::getopt and
    friends for storing command line argument options.


    That is one of the two things that came to my mind.

    The other one is the evaluation order of individual words that make up a command. Currently, everything between curly braces "{}" are delayed
    for variable substitutions, command evaluations, etc.

    However, it looks like stuff between "$(" and the matching ")" are
    treated same as "{}", which would alter the basic rules of the language.

    Perhaps adopting a new syntax like "{**}{...}" or even "{=}{...}" like
    someone else suggested, might be easier to pull into the current rules.

    Personally, I am kind of surprised that "expr {}" seems to be disliked.
    I also don't see how "$()" improves things but that's just me.

    Interesting project.


    --- Synchronet 3.21a-Linux NewsLink 1.2
  • From Rich@rich@example.invalid to comp.lang.tcl on Sun Oct 19 20:11:05 2025
    From Newsgroup: comp.lang.tcl

    saito <saitology9@gmail.com> wrote:
    On 10/17/2025 10:48 PM, Rich wrote:

    Thoughts? Does anyone see issues I haven't considered?

    It conflicts with "empty string array names":

    ...
    Now, naming an array "" is not commonly done, but I've used it (empty
    string) sometimes for the destination array for ::cmdline::getopt and
    friends for storing command line argument options.


    That is one of the two things that came to my mind.

    ...

    Personally, I am kind of surprised that "expr {}" seems to be disliked.
    I also don't see how "$()" improves things but that's just me.

    It is identical to Bash's process substitution operator [1], beyond that,
    it is less characters than [expr {}].

    But I very much suspect that it will do little to quiet the complaints
    from "other language users" who complain about [expr]. It will change
    their complaints, but it won't quiet them. Because what they are
    really complaining about is they want to see something like this:

    some-func $a+$c ($ab+$cd/($ef-$gh))

    Or more likely, what they 'really' are complaining about is that Tcl
    does not look like this to them:

    some-func a+c (ab+cd/(ef-gh))



    [1] and if it were to copy Bash, it would be $(( )) for math
    operations instead of $( )
    --- Synchronet 3.21a-Linux NewsLink 1.2
  • From saito@saitology9@gmail.com to comp.lang.tcl on Sun Oct 19 16:30:39 2025
    From Newsgroup: comp.lang.tcl

    On 10/19/2025 4:11 PM, Rich wrote:

    Personally, I am kind of surprised that "expr {}" seems to be disliked.
    I also don't see how "$()" improves things but that's just me.

    It is identical to Bash's process substitution operator [1], beyond that,
    it is less characters than [expr {}].

    I see. I have only used bash to set up aliases for commands that I use frequently so this is new to me.



    But I very much suspect that it will do little to quiet the complaints
    from "other language users" who complain about [expr]. It will change
    their complaints, but it won't quiet them. Because what they are
    really complaining about is they want to see something like this:

    some-func $a+$c ($ab+$cd/($ef-$gh))

    Or more likely, what they 'really' are complaining about is that Tcl
    does not look like this to them:

    some-func a+c (ab+cd/(ef-gh))


    It makes sense now and I agree. I see it as, everything comes with their
    own quirks, like roses and their thorns, so perhaps this is something
    about Tcl that we just need to accept with no apologies.

    However, it just occurred to me that perhaps there is a better defense,
    and I am not certain there needs to be one:

    The desired syntax (from your examples above) is limited in
    functionality: it performs the calculations once, right there. To have
    it repeated on events, triggers, etc., one will need to write a function around these expressions.

    However, Tcl offers more flexibility: you can have your expressions
    inlined as above, or you can have them execute later, without any extra
    set up or wrapper functions.

    Just my 2 cents I guess.


    --- Synchronet 3.21a-Linux NewsLink 1.2
  • From et99@et99@rocketship1.me to comp.lang.tcl on Sun Oct 19 17:08:57 2025
    From Newsgroup: comp.lang.tcl

    On 10/19/2025 12:28 PM, saito wrote:
    On 10/17/2025 10:48 PM, Rich wrote:

    Thoughts? Does anyone see issues I haven't considered?

    It conflicts with "empty string array names":

    ...
    Now, naming an array "" is not commonly done, but I've used it (empty
    string) sometimes for the destination array for ::cmdline::getopt and
    friends for storing command line argument options.


    That is one of the two things that came to my mind.

    The other one is the evaluation order of individual words that make up a command.  Currently, everything between curly braces "{}" are delayed for variable substitutions, command evaluations, etc.

    However, it looks like stuff between "$(" and the matching ")" are treated same as "{}", which would alter the basic rules of the language.

    Perhaps adopting a new syntax like "{**}{...}" or even "{=}{...}" like someone else suggested, might be easier to pull into the current rules.

    Personally, I am kind of surprised that "expr {}" seems to be disliked. I also don't see how "$()" improves things but that's just me.

    Interesting project.





    Thanks for the feedback.

    First, the easiest way to understand $(...) is that it is implemented as though it was a C #define macro but without a pre-processor step.

    The $(...) is transformed immediately into [expr {...}] before the rest of the parser ever sees it. This means that all $(...) use is the same as braced [expr] use.

    But [expr] is untouched and will work exactly the same as it always has.

    So, where's the benefit?

    Suppose you have this, where someone forgot to brace the expression:

    set bad {[file delete somefile.dat]} ;# or perhaps it came in from the wild
    set result [expr $bad + 2]

    This will throw the following error:

    can't use empty string as operand of "+"

    But your file is deleted anyway, since $bad was substituted before [expr] ever got it, and it looks exactly like this:

    set result [expr [file delete somefile.dat] + 2]

    which is valid [expr] with command substitution. To protect against this, tcl recommends all expressions be inside of braces, like so,

    set result [expr {$bad}]

    which would cause [expr] to evaluate the expression and reject it, because $bad in this context must be a number, not an expression or command.

    In addition to the security, the expression will be compiled to byte-code which is more efficient.

    So [expr] has 2 mechanisms depending on bracing while $(...) has only 1. It is an additional way to do expressions safely not a replacement for [expr].

    I won't reveal more here, but there is a new security injection bug in version 9.x that $(...) would solve, if approved.


    ------



    As to the one minor incompatibility: the array with no name, I suggest that all uses of that tcl feature should at minimum use braces, like so:

    set array_value_at_index ${(index)}

    This would eliminate the conflict $(...) creates, and would highlight the fact that the user is really using a variable name that is not comprised of the standard letters, numbers, colons, and underscores, and didn't accidentally forget to include a name.

    Yes, the manual states that the name can be empty, but the parser has to include special code to handle this, suggesting that it was an afterthought and not there in the beginning.

    I'm the first to admit that my choice of variable names is not always what it should be, but to go so far as to have a name with no name, well, I'm at a loss to see the value there. But to each ...

    Note that with $(...) there is no conflict with creating an array variable with the empty name, since that would be written as,

    set (index) some-value

    It's only when using $ substitution that there's a conflict. And there's also [set] for variables with really exotic names that can also work with empty names (and with the non-array variable "" also).

    set value [set (index)]

    So the ability is not going away, it just requires some proactive changes. If users would use one of the two methods above today, whether this $(...) feature is implemented or not, their usage would be future proofed.

    Thanks

    --et99


    --- Synchronet 3.21a-Linux NewsLink 1.2
  • From et99@et99@rocketship1.me to comp.lang.tcl on Sun Oct 19 20:46:45 2025
    From Newsgroup: comp.lang.tcl

    On 10/19/2025 1:30 PM, saito wrote:
    On 10/19/2025 4:11 PM, Rich wrote:

    [snip]


    But I very much suspect that it will do little to quiet the complaints
    from "other language users" who complain about [expr].  It will change
    their complaints, but it won't quiet them.  Because what they are
    really complaining about is they want to see something like this:

    some-func $a+$c ($ab+$cd/($ef-$gh))

    Or more likely, what they 'really' are complaining about is that Tcl
    does not look like this to them:

    some-func a+c (ab+cd/(ef-gh))


    It makes sense now and I agree. I see it as, everything comes with their own quirks, like roses and their thorns, so perhaps this is something about Tcl that we just need to accept with no apologies.

    However, it just occurred to me that perhaps there is a better defense, and I am not certain there needs to be one:

    The desired syntax (from your examples above) is limited in functionality: it performs the calculations once, right there. To have it repeated on events, triggers, etc., one will need to write a function around these expressions.

    However, Tcl offers more flexibility: you can have your expressions inlined as above, or you can have them execute later, without any extra set up or wrapper functions.

    Just my 2 cents I guess.





    Good point Rich! You're right that $(expr) won't satisfy people who want Python/C-style syntax - that's not the goal.

    The goal is to make the recommended, safe way (braced expressions) easier to read and write for people who already understand and appreciate Tcl's model. It's about improving Tcl for Tcl users, not converting people from other languages.

    Although, your first example isn't far from this TIP's proposal,

    some-func $a+$c ($ab+$cd/($ef-$gh))

    becomes

    some-func $($a+$c) $($ab+$cd/($ef-$gh))

    While this only added 4 characters, it also ensures that the result is compiled byte-code and free of injection attacks.


    Regarding saito's point on immediate vs. delayed values: $(...) works exactly the same as $var in this regard - nothing new to learn.

    If you need values looked up at event time:

    button ... -command {puts $::var}
    button ... -command {puts $($::var - 2)}


    If you need current values repeatedly:

    button ... -command [list puts $::var]
    button ... -command [list puts $($::var - 2)]


    the same patterns Tcl users already know - $(...) fits right in.

    --et99

    --- Synchronet 3.21a-Linux NewsLink 1.2
  • From saito@saitology9@gmail.com to comp.lang.tcl on Mon Oct 20 14:45:31 2025
    From Newsgroup: comp.lang.tcl

    On 10/19/2025 11:46 PM, et99 wrote:


    Regarding saito's point on immediate vs. delayed values: $(...) works exactly the same as $var in this regard - nothing new to learn.

    Thank you. I got that impression from your post from the start. What I
    was hinting at was that, the 12 rules of the language would have to be modified because of the word/argument expansion semantics which is
    suppressed only for curly braces. Unless I am mistaken, the "$(...)"
    would need to be added as an exception or a new rule or something like that.


    --- Synchronet 3.21a-Linux NewsLink 1.2
  • From et99@et99@rocketship1.me to comp.lang.tcl on Mon Oct 20 14:48:55 2025
    From Newsgroup: comp.lang.tcl

    On 10/20/2025 11:45 AM, saito wrote:
    On 10/19/2025 11:46 PM, et99 wrote:


    Regarding saito's point on immediate vs. delayed values: $(...) works exactly the same as $var in this regard - nothing new to learn.

    Thank you. I got that impression from your post from the start.  What I was hinting at was that, the 12 rules of the language would have to be modified because of the word/argument expansion semantics which is suppressed only for curly braces.  Unless I am mistaken, the "$(...)" would need to be added as an exception or a new rule or something like that.



    Yes, you are correct.

    Rule 8, currently called "Variable substitution" would need to be changed. Perhaps it would then be called $ substitution. I think that $(expression) would fit in nicely after ${name}.

    The sentence in $name(index) that says "and may be an empty string" would then be moved down to the ${name} section since that would be the appropriate way to use a null string as an array name *or* a variable name.

    BTW, the manual is incomplete here, since name can also be null for a non-array variable but this is never mentioned:

    % set {} foo
    foo
    % puts ${}
    foo
    % unset {}
    % set "" nothing
    nothing
    % puts ${}
    nothing
    % info glob
    {} tcl_rcFileName...
    % string length [lindex [info glob] 0]
    0
    % set foo $
    $

    So, it's not a variable with the name "{}" it is the null string that is the name. And the ${} is required if you want the null variable, since otherwise a $ alone is not a substitution.

    --et99

    --- Synchronet 3.21a-Linux NewsLink 1.2
  • From et99@et99@rocketship1.me to comp.lang.tcl on Mon Oct 20 15:27:09 2025
    From Newsgroup: comp.lang.tcl

    On 10/20/2025 2:48 PM, et99 wrote:
    On 10/20/2025 11:45 AM, saito wrote:

    Thank you. I got that impression from your post from the start.  What I was hinting at was that, the 12 rules of the language would have to be modified because of the word/argument expansion semantics which is suppressed only for curly braces.  Unless I am mistaken, the "$(...)" would need to be added as an exception or a new rule or something like that.

    And yes again, you are correct, it would need to mention that $(...) suppresses direct substitution of variables or commands which are passed on to expr (or probably the compiler) that does further validation and evaluation.

    Hmmm, I just now discovered something I hadn't realized:

    % set (1) one
    one
    % set ind 1
    1
    % set ($ind)
    one
    % puts ${($ind)}
    can't read "($ind)": no such element in array

    This means that the ${name} workaround for an empty array name will NOT work for an index that is a $var. So, this means that the [set ($var)] method would have to be used, not the ${($var)}. So, this is part of the rule for ${name} which also does not substitute inside {}'s but is not the same as the rule on words enclosed in {}.

    Learn something new about tcl all the time...

    -et99

    --- Synchronet 3.21a-Linux NewsLink 1.2
  • From rene@user4652@newsgrouper.org.invalid to comp.lang.tcl on Tue Oct 21 08:04:16 2025
    From Newsgroup: comp.lang.tcl


    Hello

    I currently do not see the benefit of this proposal, except some char less to type.
    IMHO expr has some problems or room for enhancements:
    1. Double evaluation of arguments
    Could be solved with a new command with only 1 argument
    2. Returns only one value
    See p.e. tip 647 syntax
    3. Access to tcl-variables with $-syntax
    This would require a new expression parser
    4. Anything else?

    Do the tip 672 solve one of these points?


    Regards
    rene
    PS. This is a copy from my post to tcl-core
    --- Synchronet 3.21a-Linux NewsLink 1.2
  • From Colin Macleod@user7@newsgrouper.org.invalid to comp.lang.tcl on Wed Oct 22 10:12:01 2025
    From Newsgroup: comp.lang.tcl

    et99 <et99@rocketship1.me> posted:

    On 10/18/2025 4:30 AM, Colin Macleod wrote:

    I certainly agree that a streamlined expression syntax would eliminate
    one of the biggest warts that tends to put people off Tcl.

    Thank you for the support and for your willingness to consolidate efforts! It's encouraging to see convergence around addressing this long-standing issue.

    After seeing lots of quibbling about compatibility on the tcl-core list
    I'm thinking maybe it's not yet time to write off my own suggestion.
    So I sent the following to tcl-core:

    ========================================================================
    Hi All, perhaps it's time to boost my own expr proposal again.

    I like the [= <expr>] idea, but simply aliasing "=" to expr doesn't help
    much because you still need to brace the expression to avoid double- substitution problems. Unbraced works ok for the simple examples Florent gives, but in general is problematic, e.g.

    set x {[exec cat /secret/file >/dev/tty]} ;# x might be set from user input ...
    string range "abcdef" 1 end-[= $x-2] ;# user sees secret file :-(

    My own TIP 676 is a proposal to make [= <expression>] usable and safe.
    It has the advantage of not requiring any change to the dodekalogue and
    is fully compatible with existing code. It also can be used anywhere
    that [] gets expanded including within quoted strings, which is not the
    case for the {=}{expr} proposal.

    There are some downsides:
    - Operators and operands need to be separated with spaces, i.e. [= $x - 2]
    not [= $x-2]
    - Only numerical and boolean values can be supported, not string values
    - Lazy evaluation of && || ?: is not supported
    - The implementation is a little more complicated since it can't use the
    existing [expr] parser. I supplied a Tcl prototype, linked from the TIP,
    actual implementation would require translating this into C.

    I worked on this in 2023 but put it aside because everyone was focussed
    on getting 9.0 released, then I moved on to a different project. I think
    it's worth considering now that [expr] simplification is back in the spotlight.

    Colin.
    ========================================================================

    My TIP is at https://core.tcl-lang.org/tips/doc/trunk/tip/676.md .
    I do think any of the proposals on the table would be better than
    doing nothing though.
    --
    Colin Macleod ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ https://cmacleod.me.uk

    FEED FEED FEED FEED FEED FEED FEED FEED
    GAZA GAZA GAZA GAZA GAZA GAZA GAZA GAZA
    NOW! NOW! NOW! NOW! NOW! NOW! NOW! NOW!
    --- Synchronet 3.21a-Linux NewsLink 1.2
  • From et99@et99@rocketship1.me to comp.lang.tcl on Wed Oct 22 05:38:14 2025
    From Newsgroup: comp.lang.tcl

    On 10/22/2025 3:12 AM, Colin Macleod wrote:
    et99 <et99@rocketship1.me> posted:

    On 10/18/2025 4:30 AM, Colin Macleod wrote:

    I certainly agree that a streamlined expression syntax would eliminate
    one of the biggest warts that tends to put people off Tcl.

    Thank you for the support and for your willingness to consolidate efforts! >> It's encouraging to see convergence around addressing this long-standing issue.

    After seeing lots of quibbling about compatibility on the tcl-core list
    I'm thinking maybe it's not yet time to write off my own suggestion.
    So I sent the following to tcl-core:

    ========================================================================
    Hi All, perhaps it's time to boost my own expr proposal again.

    I like the [= <expr>] idea, but simply aliasing "=" to expr doesn't help
    much because you still need to brace the expression to avoid double- substitution problems. Unbraced works ok for the simple examples Florent gives, but in general is problematic, e.g.

    set x {[exec cat /secret/file >/dev/tty]} ;# x might be set from user input
    ...
    string range "abcdef" 1 end-[= $x-2] ;# user sees secret file :-(

    My own TIP 676 is a proposal to make [= <expression>] usable and safe.
    It has the advantage of not requiring any change to the dodekalogue and
    is fully compatible with existing code. It also can be used anywhere
    that [] gets expanded including within quoted strings, which is not the
    case for the {=}{expr} proposal.

    There are some downsides:
    - Operators and operands need to be separated with spaces, i.e. [= $x - 2]
    not [= $x-2]
    - Only numerical and boolean values can be supported, not string values
    - Lazy evaluation of && || ?: is not supported
    - The implementation is a little more complicated since it can't use the
    existing [expr] parser. I supplied a Tcl prototype, linked from the TIP,
    actual implementation would require translating this into C.

    I worked on this in 2023 but put it aside because everyone was focussed
    on getting 9.0 released, then I moved on to a different project. I think it's worth considering now that [expr] simplification is back in the spotlight.

    Colin. ========================================================================

    My TIP is at https://core.tcl-lang.org/tips/doc/trunk/tip/676.md .
    I do think any of the proposals on the table would be better than
    doing nothing though.


    Colin:

    Yes, the community approach sometimes leads to the inability to make a decision one way or the other. I've put the wraps on this, you can see my recent posting on the core list.

    I've modified my code to have a #define mode option which can implement either of the original syntax $(...) or Don's idea of $=(...) where the = could be any of the non-substitution characters, like @ or ^ which I believe eliminates the conflict with the null string array variable name. Just 1 extra character.

    I was encouraged to find that several core team members were quite supportive, but I needed to finalize my prototype and let them make the next move.

    Feel free to use the code for your own implementation, by using the macro approach, it's under 100 lines, and you might be able to build a safe [= ...] that feeds into expr braced expressions.

    I chose the $ injection point you could look at the [...] interface, or write up a C extension that could do the same thing. It's not that difficult to build a command token and pass it off to if you wedge it in at the right place.

    Good luck with your proposal.

    -et99

    --- Synchronet 3.21a-Linux NewsLink 1.2
  • From Rich@rich@example.invalid to comp.lang.tcl on Wed Oct 22 12:56:27 2025
    From Newsgroup: comp.lang.tcl

    et99 <et99@rocketship1.me> wrote:

    I've modified my code to have a #define mode option which can
    implement either of the original syntax $(...) or Don's idea of
    $=(...) where the = could be any of the non-substitution characters,
    like @ or ^ which I believe eliminates the conflict with the null
    string array variable name. Just 1 extra character.

    Equals seems fine as a character, and at least suggests "math" as well
    as making a math equation somewhat read like a written one:

    set a $=($y*4+$z**2) ;# set a "equals" to 4*$y plus $z squared

    It also, it seems, does not conflict with any existing code usage of $
    as $= does not expand:

    $ rlwrap tclsh
    % array set = [list a 1 b 2 c 3]
    % puts $=(b)
    $=(b)
    % puts $=(b)
    $=(b)
    % set =(b)
    2
    % puts ${=(b)}
    2

    So while one can have an array named =, one could not use plain $=() to
    access it, so using $= for your new math operator won't conflict with
    any existing code (which would have already had to use 'set' or ${} to
    access an "array named equals").

    I was encouraged to find that several core team members were quite supportive, but I needed to finalize my prototype and let them make
    the next move.

    I suggest falling behind the $=() syntax, as it looks to remove *any* complaints of breaking legacy code.

    --- Synchronet 3.21a-Linux NewsLink 1.2
  • From et99@et99@rocketship1.me to comp.lang.tcl on Wed Oct 22 12:48:25 2025
    From Newsgroup: comp.lang.tcl

    On 10/22/2025 5:56 AM, Rich wrote:

    Equals seems fine as a character, and at least suggests "math" as well
    as making a math equation somewhat read like a written one:

    set a $=($y*4+$z**2) ;# set a "equals" to 4*$y plus $z squared

    It also, it seems, does not conflict with any existing code usage of $
    as $= does not expand:

    $ rlwrap tclsh
    % array set = [list a 1 b 2 c 3]
    % puts $=(b)
    $=(b)
    % puts $=(b)
    $=(b)
    % set =(b)
    2
    % puts ${=(b)}
    2

    So while one can have an array named =, one could not use plain $=() to access it, so using $= for your new math operator won't conflict with
    any existing code (which would have already had to use 'set' or ${} to
    access an "array named equals").

    [snip]

    I suggest falling behind the $=() syntax, as it looks to remove *any* complaints of breaking legacy code.


    Thanks Rich for verifying that.

    I like your example emphasizing the set ... = ... math expression, as indeed that does seem to fit well. If you find this proposal to your liking, I would encourage you to send a note off to the core email list.

    Input from the outer Tcl community can be valuable to help the core make a decision.

    --et99

    --- Synchronet 3.21a-Linux NewsLink 1.2