• question about array traces

    From Petro Kazmirchuk@vivid.tree7955@fastmail.com to comp.lang.tcl on Sat May 9 22:10:34 2026
    From Newsgroup: comp.lang.tcl

    TLDR: it seems to me that "trace add variable my_array {array ...}
    cmdPrefix" has rather limited use compared to {read write unset}, so
    I'll really appreciate any real world docs/examples on how and when I am supposed to use it (or Tcl_TraceVar+TCL_TRACE_ARRAY in C).

    Background: I have a Tcl 8.6/C++ app that exposes a tree-like C++
    structure as a Tcl array: $my_array(key/subkey/subkey)
    Users can:
    - read a value using a key
    - write a value using a key
    - delete a value with [unset]
    - use [array names]/get/set with a glob-pattern/* to query a subset of
    this structure

    This is implemented only in C++ with Tcl_TraceVar.
    Although back then (years ago) the array-like API seemed simple and convenient, now I can see its limitations and rather complex C++ code,
    so I'm trying to refactor it by:
    - moving as much logic as possible from C++ to Tcl
    - making C++ a thin layer that returns an opaque handle to the structure
    and implements a set of functions to work with it
    - making a proper Tcl ensemble for full access to the functionality
    - on top of this ensemble I'm reimplementing the "traced Tcl array" API
    for backwards compatibility with 1000s LoC that my users have written
    over years. So, I've moved from Tcl_TraceVar to "trace add variable
    array_name {array read write unset}"

    I'm done with the read/write/unset part, this was straightforward. In
    many cases users know keys in advance, and then it's enough. But often
    they need to discover keys dynamically using [array names] etc, and for
    this I must use the "array" ops, which after some thinking and looking
    around does seem like an afterthought with serious limitations. When
    this trace is invoked:

    1. I don't know which subcommand caused it (names/get/set/size?)
    2. I don't know what the glob pattern was
    3. so, it forces me to populate the whole array with keys *and* values,
    which might be expensive, even if a user is asking smth like [array
    names key/subkey*] which will eventually return only a small subset of keys.
    4. Finally, I have no way to distinguish [info exists my_array(key)]
    from a normal read trace.

    I guess, I can work around these limitations with [dict get [info frame
    -2] cmd], but this looks like an awful hack, and I'm not sure how
    reliable it is.

    So, before I dig deeper, I'm looking around for real-world examples of
    how it was supposed to be used *properly*, and what pitfalls I might encounter.
    BTW I did check the Ashok's book, and it doesn't go into much detail in
    this aspect either (understandably so, it's very thick already)

    thanks in advance!
    Petro


    --- Synchronet 3.22a-Linux NewsLink 1.2
  • From abu@user13892@newsgrouper.org.invalid to comp.lang.tcl on Mon May 18 20:35:00 2026
    From Newsgroup: comp.lang.tcl


    Sorry if this may seem like a silly question, but what's the point of putting a trace on the reading of a variable (or an element of an array)?
    --- Synchronet 3.22a-Linux NewsLink 1.2
  • From saito@saitology9@gmail.com to comp.lang.tcl on Mon May 18 21:57:52 2026
    From Newsgroup: comp.lang.tcl

    On 5/18/2026 4:35 PM, abu wrote:

    Sorry if this may seem like a silly question, but what's the point of putting a trace on the reading of a variable (or an element of an array)?

    Maybe used for debugging?
    --- Synchronet 3.22a-Linux NewsLink 1.2
  • From Rich@rich@example.invalid to comp.lang.tcl on Tue May 19 03:54:47 2026
    From Newsgroup: comp.lang.tcl

    abu <user13892@newsgrouper.org.invalid> wrote:

    Sorry if this may seem like a silly question, but what's the point of putting a trace on the reading of a variable (or an element of an
    array)?

    One use is as a way to generate events in plain Tcl (no Tk) code.

    Also keep in mind that once the plumbing is built for tracing writes, providing traces for reads is almost all but free.

    --- Synchronet 3.22a-Linux NewsLink 1.2
  • From Colin Macleod@user7@newsgrouper.org.invalid to comp.lang.tcl on Tue May 19 08:45:08 2026
    From Newsgroup: comp.lang.tcl

    abu <user13892@newsgrouper.org.invalid> posted:


    Sorry if this may seem like a silly question, but what's the point of
    putting a trace on the reading of a variable (or an element of an array)?

    One use is to have the tracing code *update* the value of the variable
    that's being read, e.g. to have it automatically track some external data.
    --
    Colin Macleod ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ https://cmacleod.me.uk

    FEED HOUSE SAVE FEED HOUSE SAVE FEED HOUSE SAVE
    GAZA GAZA GAZA GAZA GAZA GAZA GAZA GAZA GAZA
    NOW! NOW! NOW! NOW! NOW! NOW! NOW! NOW! NOW!
    --- Synchronet 3.22a-Linux NewsLink 1.2
  • From Petro Kazmirchuk@vivid.tree7955@fastmail.com to comp.lang.tcl on Wed May 20 20:51:08 2026
    From Newsgroup: comp.lang.tcl

    On 19/05/2026 10:45, Colin Macleod wrote:
    abu <user13892@newsgrouper.org.invalid> posted:


    Sorry if this may seem like a silly question, but what's the point of
    putting a trace on the reading of a variable (or an element of an array)?

    One use is to have the tracing code *update* the value of the variable
    that's being read, e.g. to have it automatically track some external data.


    - simpler alternative to callbacks: an object can notify about its
    $status or $new_data or $last_error through a variable that external
    code can trace with op=write and invoke a callback
    - testing: e.g. a variable is a channel, so a test framework can trace
    it and wait until it is initialized, and then replace the real channel
    with a "mock", e.g. reflected or transformation channel
    - interface to C data, as I explained in my first message

    in short, traces are amazing, and you won't find them in any other language
    --- Synchronet 3.22a-Linux NewsLink 1.2
  • From Ralf Fassel@ralfixx@gmx.de to comp.lang.tcl on Thu May 21 11:18:25 2026
    From Newsgroup: comp.lang.tcl

    * Petro Kazmirchuk <vivid.tree7955@fastmail.com>
    | On 19/05/2026 10:45, Colin Macleod wrote:
    | > abu <user13892@newsgrouper.org.invalid> posted:
    | >
    | >>
    | >> Sorry if this may seem like a silly question, but what's the point of
    | >> putting a trace on the reading of a variable (or an element of an array)? --<snip-snip>--
    | - simpler alternative to callbacks: an object can notify about its
    | $status or $new_data or $last_error through a variable that external
    | code can trace with op=write and invoke a callback
    --<snip-snip>--

    | in short, traces are amazing, and you won't find them in any other language

    However, when used excessively for control flow, traces can be a
    nightmare to debug or refactor, since you don't see the command flow
    from the code directly.

    A simple
    set foo bar
    can have arbitrary side effects, depending on which module has set up
    the trace, whereas with callbacks you at least see in the code that
    there is something going on.

    If at some point, the setting of the variable is removed for any reason,
    the code follows a different path, and you might not even be aware of
    that. With a callback to be removed, you at least see that you need to
    check where/how the callback is used.

    My €0.01
    R'
    --- Synchronet 3.22a-Linux NewsLink 1.2