• Re: can this work?

    From Rich@21:1/5 to saito on Sat Mar 22 15:11:37 2025
    saito <saitology9@gmail.com> wrote:
    On 3/21/2025 6:56 PM, Rich wrote:

    When the parser is parsing the command, the third "word" of the first
    for loop is:

    "\$i $op \$q"

    Due to rule four, variable substitution and backslash substution is
    performed on this word, because it is double quoted.

    I read "double quoted" a few times - I think you meant "double-quote'd".

    So since it double-quoted, the substitutions occur as you described. And whatever results from that becomes a "static" argument/parameter to the for-loop. Is this right?

    The argument is always a "static" argument. With double quotes (the
    name of ASCII character \ux22) it undergoes a first round of quoting
    when the parser is first parsing the command (before the for loop
    executes) and then is parsed by "expr" on each iteration of the loop.

    I recall warnings against using double quotes with loops since the substitution occurs once.

    That depends upon what the initial string in the source is.

    This:
    set i 0 ; set op < ; set q 5
    for {} "$i $op $q" {} {...}

    Will have the parser, in the inital parse of the command, replace i, op
    and q with "0 < 5" and pass that final string to the for loop, and on
    each iterationn of the loop, the loop runs expr on "0 < 5" and yes,
    this is a "static" value and the loop runs forever (or until you kill
    it).

    However, that above was not the original example.

    What was in the original example was:
    set i 0 ; set op < ; set q 5
    for {} "\$i $op \$q" {} {...}

    The back slashes in "\$i < \$q" are of critical importance. Their
    presence make this **not** a static loop situation. The reason why is
    during the first level parse, before the for loop is even run, only one variable is substituted (the op variable). What gets passed to the for
    command by the parser is "$i < $q", which, when passed to expr, will
    look up the current values of i and q to use for the comparison,
    resulting in a loop that terminates (assuming the i and q variables are
    updated by the loop iterations).

    I guess I could benefit from this if you explain why the for-loop keeps re-evaluating a double-quoted string.

    The for command is defined as always running expr on the middle
    argument. Whether you get a loop that looks up variable contents by
    that expr call to make the check dynamic, or a loop that runs expr on
    the exact same static values for each iteration, depends upon what you
    pass to the command. That depends upon what you write that is parsed
    by the Tcl parser.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Simon Geard@21:1/5 to saito on Tue Mar 25 12:50:53 2025
    On 21/03/2025 14:32, saito wrote:
    On 3/21/2025 10:25 AM, saito wrote:
    Consider:

    set q 10
    se op "<"
    for {set i 1} {$i $op $q} {incr i} {puts $i}

    The answer is yes if you put it in an [expr] :-)

    The answer is also yes if you use ::tcl::mathop

    set q 10
    set op "<"
    namespace import ::tcl::mathop::$op
    for {set i 1} {[$op $i $q]} {incr i} {puts $i}

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From et99@21:1/5 to Rich on Tue Mar 25 21:40:11 2025
    On 3/22/2025 8:11 AM, Rich wrote:

    --snip--

    The for command is defined as always running expr on the middle
    argument. Whether you get a loop that looks up variable contents by
    that expr call to make the check dynamic, or a loop that runs expr on
    the exact same static values for each iteration, depends upon what you
    pass to the command. That depends upon what you write that is parsed
    by the Tcl parser.





    Actually, the manual for the [for] command does not say it runs [expr], rather, it only says:

    Then it repeatedly evaluates test as an expression;

    And the command [expr] is not mentioned at all. Also, in the page with the 12 rules, it never defines the word expression.

    The [if] command, however, does mention the use of [expr]:

    The if command evaluates expr1 as an expression (in the same way that expr evaluates its argument).

    I suppose one has to get deep into the weeds and fully understand the algorithm of [expr] to be able to parse it all. There, [expr] does define an expression.

    One item that took me forever to understand is why in most commands, words such as in these 3,

    set foo bar
    set foo {bar}
    set foo "bar"

    the 2 types of quotes don't change the result here from the unquoted version. But in [expr] and therefore also in the first argument to [if] and the second to [for] a string has to be quoted in one of the 2 ways. So that,

    if {$foo eq "bar"} ..
    if {$foo eq {bar}} ..

    is ok, but

    if {$foo eq bar} ..

    is not ok. And the reason is that,

    expr {$foo eq bar}

    also produces an error since operands in [expr] are not the same as tcl words. Here, [expr] complains about a bare word - something I've also not seen defined.

    Anyway, there's always something to learn here :)

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From et99@21:1/5 to Alan Grunwald on Thu Mar 27 11:24:44 2025
    On 3/26/2025 5:35 AM, Alan Grunwald wrote:


    FWIW, I remember when I first started to use [expr {$a eq "b"}] if took me *AGES* to get the syntax right. To be fair to [expr], its error message (if you omit the double-quotes) is pretty specific, but I still found it a struggle to get the syntax
    right.

    The lesson I took from this was to stop writing

    set i foo

    and to start writing

    set i "foo"

    but the temptation to save a couple of keystrokes is still strong :-)



    I too have taken to always use the double quotes, first it better indicates my intent, but also my text editor highlights all "strings" in red so it's much easier to see them. This provides my incentive :)

    While I was certainly nitpicking, it does show how difficult it can be to describe a computer language in a language like English. For years I thought it had to be in ""'s because that's how one normally writes strings. Then one day I read [expr] (for
    the n-teenth time) and finally realized one could also use braces, but one of the two is required. That's when the light-bulb finally glowed for me :)

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Emiliano@21:1/5 to saito on Fri Mar 21 16:34:20 2025
    On Fri, 21 Mar 2025 10:25:17 -0400
    saito <saitology9@gmail.com> wrote:

    Consider:

    set q 10
    set op "<"
    for {set i 1} {$i $op $q} {incr i} {puts $i}

    Several. Here are two

    for {set i 1} "\$i $op \$q" {incr i} {puts $i}

    or

    for {set i 1} [format {$i %s $q} $op] {incr i} {puts $i}

    Regards

    --
    Emiliano

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Rich@21:1/5 to saito on Fri Mar 21 22:56:01 2025
    saito <saitology9@gmail.com> wrote:
    On 3/21/2025 3:34 PM, Emiliano wrote:
    On Fri, 21 Mar 2025 10:25:17 -0400

    Several. Here are two

    for {set i 1} "\$i $op \$q" {incr i} {puts $i}

    or

    for {set i 1} [format {$i %s $q} $op] {incr i} {puts $i}


    Nice solutions, especially the former one. I am surprised that the double-quotes work here, with repeated evaluations. Nice approach.
    And [format] looks suspicious in its use here :-)

    Remember the rules of Tcl [1]:

    [4]
    If the first character of a word is double-quote (``"'') then the
    word is terminated by the next double-quote character. If
    semi-colons, close brackets, or white space characters (including
    newlines) appear between the quotes then they are treated as
    ordinary characters and included in the word. Command
    substitution, variable substitution, and backslash substitution are
    performed on the characters between the quotes as described below.
    The double-quotes are not retained as part of the word.

    When the parser is parsing the command, the third "word" of the first
    for loop is:

    "\$i $op \$q"

    Due to rule four, variable substitution and backslash substution is
    performed on this word, because it is double quoted.

    So $op is replaced with <, and both \$ are replaced with $

    Resulting in |$i < $q| ( | to show edges of the "word").

    Then the 'for' command is called, with it's second parameter being
    $i < $q

    The for loop then calls expr on this parameter, and expr looks up the
    value of the i and q variables, and tests them for less than. If the
    result is true, the loop continues, if the result is false, the loop
    stops.


    [1] https://www.tcl-lang.org/man/tcl8.2.3/TclCmd/Tcl.htm

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)