• How to call procs that use each-others data

    From Cecil Westerhof@21:1/5 to All on Sat May 7 06:08:53 2022
    I had the following code:
    set swapDict [fillSwapDict]
    set swapDict [mergeSwapDict ${swapDict} ${mergeList}]
    set swapList [sortedList ${swapDict}]
    displayList ${swapList} ${end}

    Each call does use the data of the call before it. So I thought it is
    better to write it like this:
    displayList [sortedList [mergeSwapDict [fillSwapDict] ${mergeList}]] ${end}

    Which is the 'better' way, or is another way better?

    --
    Cecil Westerhof
    Senior Software Engineer
    LinkedIn: http://www.linkedin.com/in/cecilwesterhof

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Rich@21:1/5 to Cecil Westerhof on Sat May 7 12:39:07 2022
    Cecil Westerhof <Cecil@decebal.nl> wrote:
    I had the following code:
    set swapDict [fillSwapDict]
    set swapDict [mergeSwapDict ${swapDict} ${mergeList}]
    set swapList [sortedList ${swapDict}]
    displayList ${swapList} ${end}

    Each call does use the data of the call before it. So I thought it is
    better to write it like this:
    displayList [sortedList [mergeSwapDict [fillSwapDict] ${mergeList}]] ${end}

    Which is the 'better' way, or is another way better?

    There isn't. You are slowly moving closer to merely a "stylistic"
    issue on the order of whether this:

    if (...) {
    ...
    }

    or this

    if (...)
    {
    ...
    }

    Arrangement of the openbrace for a C if clause is the "better way".

    The second is more LISP like, and avoids having to allocate, and
    ultimately destroy, three variables. But you will find people who
    argue with convincing reasons why either is 'better' than the other.

    Use whichever you prefer, and don't fret over it. Myself I use the
    LISP like layout mostly, but will use the tempvar version on occasion
    (and esp. if one of the tempvar version can avoid processing the same
    data into the same result two or more times).

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Cecil Westerhof@21:1/5 to Rich on Sat May 7 15:44:00 2022
    Rich <rich@example.invalid> writes:

    Cecil Westerhof <Cecil@decebal.nl> wrote:
    I had the following code:
    set swapDict [fillSwapDict]
    set swapDict [mergeSwapDict ${swapDict} ${mergeList}]
    set swapList [sortedList ${swapDict}]
    displayList ${swapList} ${end}

    Each call does use the data of the call before it. So I thought it is
    better to write it like this:
    displayList [sortedList [mergeSwapDict [fillSwapDict] ${mergeList}]] ${end}

    Which is the 'better' way, or is another way better?

    There isn't. You are slowly moving closer to merely a "stylistic"
    issue on the order of whether this:

    if (...) {
    ...
    }

    or this

    if (...)
    {
    ...
    }

    Arrangement of the openbrace for a C if clause is the "better way".

    Personally I prefer the first, but if I would work somewhere where
    they prefer the second, I would use the second.


    The second is more LISP like, and avoids having to allocate, and
    ultimately destroy, three variables. But you will find people who
    argue with convincing reasons why either is 'better' than the other.

    Yes, that is why I prefer the second. But when sharing your code (what
    I intend to do) it is best to use a style that most people understand
    better.


    Use whichever you prefer, and don't fret over it. Myself I use the
    LISP like layout mostly, but will use the tempvar version on occasion
    (and esp. if one of the tempvar version can avoid processing the same
    data into the same result two or more times).

    I added extra functionality and for that I put the first tempvar back.
    Shaved about a third of the execution time.

    --
    Cecil Westerhof
    Senior Software Engineer
    LinkedIn: http://www.linkedin.com/in/cecilwesterhof

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Robert Heller@21:1/5 to Rich on Sat May 7 09:32:37 2022
    At Sat, 7 May 2022 12:39:07 -0000 (UTC) Rich <rich@example.invalid> wrote:


    Cecil Westerhof <Cecil@decebal.nl> wrote:
    I had the following code:
    set swapDict [fillSwapDict]
    set swapDict [mergeSwapDict ${swapDict} ${mergeList}]
    set swapList [sortedList ${swapDict}]
    displayList ${swapList} ${end}

    Each call does use the data of the call before it. So I thought it is better to write it like this:
    displayList [sortedList [mergeSwapDict [fillSwapDict] ${mergeList}]] ${end}

    Which is the 'better' way, or is another way better?

    There isn't. You are slowly moving closer to merely a "stylistic"
    issue on the order of whether this:

    if (...) {
    ...
    }

    or this

    if (...)
    {
    ...
    }

    Arrangement of the openbrace for a C if clause is the "better way".

    The second is more LISP like, and avoids having to allocate, and
    ultimately destroy, three variables. But you will find people who
    argue with convincing reasons why either is 'better' than the other.

    Use whichever you prefer, and don't fret over it. Myself I use the
    LISP like layout mostly, but will use the tempvar version on occasion
    (and esp. if one of the tempvar version can avoid processing the same
    data into the same result two or more times).

    The only other issue is source code readablity. *Sometimes* you end up with either a really long line (which does not "fit" on your screen, unless you
    have an insanely large edit windows and/or are using a really small font), or an insanely large number of continue lines (and possibly really large indenting). Sometime breaking up a large and complex expression into subexpressions results in code that is easier to read and understand (and in some cases easier to debug).




    --
    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

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From jtyler@21:1/5 to Robert Heller on Sat May 7 10:43:45 2022
    On 5/7/2022 7:32 AM, Robert Heller wrote:

    The only other issue is source code readablity. *Sometimes* you end up with either a really long line (which does not "fit" on your screen, unless you have an insanely large edit windows and/or are using a really small font), or an insanely large number of continue lines (and possibly really large indenting). Sometime breaking up a large and complex expression into subexpressions results in code that is easier to read and understand (and in some cases easier to debug).





    Cecil:

    I totally agree with Robert, especially with debugging.

    I will often go even further and create more specific temporary
    variables, since it often results in more self-explanatory code:

    set filledDict [fillSwapDict]
    set mergedDict [mergeSwapDict ${filledDict} ${mergeList}]
    set swapList [sortedList ${mergedDict}]


    But the primary reason is that if you create one functional style
    statement with nested proc/command calls, it becomes quite difficult to
    tell which of the intermediate steps isn't working correctly when the
    final result is not as expected.

    To that end, with my editor, I can do 4 drag and drop copies of those
    variables onto a single line, like so:

    filledDict mergedDict swapList mergeList

    then a triple click on the line selects the 4 and 1 keystroke launches
    an external editor tool where the 4 variables are sent to a tcl program
    and returned with this text to replace the 4:

    puts "filledDict= |$filledDict| mergedDict= |$mergedDict| ..."

    I might then add some newlines to this, or [lsort] them etc.

    Given the speed of computers these days, I seldom write more than a few
    lines of code before I hit my launch key in the editor which will write
    out the file and launch it as the arg to a tclkit. In about 1 second, I
    will have a console window in front of me with the output of that puts
    right there. A [vwait ::ffff] can work like a breakpoint there as well.

    I find that this is far easier and quicker than to navigate to the code
    in some sort of single stepping and break-point setting debugging tool.

    And when done, I comment them out, and usually right indent the puts
    past say column 50 so they're still right there if needed again while
    not making the real code hard to see.

    I tend to build bottom-up and so I develop small functional procedures
    that I can grow and debug independent of the rest of some program. Later
    I glue the pieces together after I know they are all working correctly.

    Hope this helps.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From mango@21:1/5 to All on Sat May 7 18:21:57 2022
    This is Tcl. If you don't like the way it looks, create commands to make it look the way you want. Perhaps the wiki page on pipeline programming has some ideas of one way to deal with deeply nested commands.
    https://wiki.tcl-lang.org/page/Pipeline+programming.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From apn@21:1/5 to Robert Heller on Sun May 8 11:26:11 2022
    On 5/7/2022 8:02 PM, Robert Heller wrote:
    The only other issue is source code readablity. *Sometimes* you end up with either a really long line (which does not "fit" on your screen, unless you have an insanely large edit windows and/or are using a really small font), or an insanely large number of continue lines (and possibly really large indenting). Sometime breaking up a large and complex expression into subexpressions results in code that is easier to read and understand (and in some cases easier to debug).


    While I agree with the above in terms of readability, note that
    temporary variables can have an significant impact on performance when
    dealing with even moderately large data. It's not the temporary variable
    itself but rather Tcl's reference counting and COW implementation means
    that the additional variable reference does not allow Tcl's in-place modification optimization. Consider for example,

    % proc p {} {lrepeat 10000 x}
    % timerate -calibrate p; # Tell timerate to ignore overhead of p - not
    relevant
    46.01236794640557 µs/#-overhead 48.2837 µs/# 40428 # 20710.9 #/sec
    % timerate {linsert [p] end x}
    4.052869 µs/# 19974 # 246738 #/sec 80.952 net-ms
    % timerate {set l [p]; linsert $l end x}
    59.1994 µs/# 9505 # 16892.1 #/sec 562.690 net-ms

    The temp version is slower by an order of magnitude. Of course, this is
    only true when the value returned by the procedure does not have another reference elsewhere in which case the additional temp reference will not matter. It's just another consideration to keep in mind.

    /Ashok

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