• unset fails with no error

    From et4@21:1/5 to All on Fri Oct 14 16:17:41 2022
    In the following, the variable foo is associated with the text entry .e. If foo is unset, then [unset] silently (no error) returns but foo still exists. When the text entry is destroyed, then foo can be truly unset.

    I would think that the unset should work a bit like file system file deletes. If the file is open, the delete becomes a pending delete until all connections are closed.

    Or at minimum, shouldn't the attempt to unset throw an error (since -nocomplain is not used).


    % entry .e -textvariable foo
    .e
    % pack .e
    % ::tcl::unsupported::representation $foo
    value is a pure string with a refcount of 2, object pointer at 04C4A6B0, string representation ""
    % set foo bar
    bar
    % ::tcl::unsupported::representation $foo
    value is a pure string with a refcount of 4, object pointer at 031C9FE8, string representation "bar"
    % unset foo
    % ::tcl::unsupported::representation $foo
    value is a pure string with a refcount of 2, object pointer at 031C9B68, string representation "bar"
    % unset foo
    % ::tcl::unsupported::representation $foo
    value is a pure string with a refcount of 2, object pointer at 031C9E98, string representation "bar"
    % destroy .e
    % ::tcl::unsupported::representation $foo
    value is a pure string with a refcount of 2, object pointer at 031C9E98, string representation "bar"
    % unset foo
    % ::tcl::unsupported::representation $foo
    can't read "foo": no such variable


    If I set foo first, the results are the same, unset simply returns.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Rich@21:1/5 to [email protected] on Sat Oct 15 02:14:35 2022
    et4 <[email protected]> wrote:
    In the following, the variable foo is associated with the text entry
    .e. If foo is unset, then [unset] silently (no error) returns but
    foo still exists. When the text entry is destroyed, then foo can be
    truly unset.

    I would think that the unset should work a bit like file system file
    deletes. If the file is open, the delete becomes a pending delete
    until all connections are closed.

    Why would you think this? A programming language is not a filesystem,
    and not all file systems follow the Unix filesystem model of allowing
    deletes of open files.

    Or at minimum, shouldn't the attempt to unset throw an error (since -nocomplain is not used).

    According to the man page, an error is thrown because:

    An error can occur when the named variable does not exist, or the
    name refers to an array element but the variable is a scalar, or the
    name refers to a variable in a non-existent namespace.

    foo exists, so the "does not exist" part is not thrown. You are not
    unsetting an array element when foo is scalar, so part two is not
    thrown, and you are not referencing a non-existent namespace, so part
    three is not thrown.

    So throwing no errors seems fully within the documentation of how unset
    works.

    The only 'quirk' is that foo does not go away because the entry is also connected to it via the textvariable option (and this is probably why
    it does not actually go away).

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From et4@21:1/5 to Rich on Fri Oct 14 20:53:51 2022
    On 10/14/2022 7:14 PM, Rich wrote:
    et4 <[email protected]> wrote:


    Why would you think this? A programming language is not a filesystem,
    and not all file systems follow the Unix filesystem model of allowing
    deletes of open files.


    Hmmm, maybe the principle of least astonishment. I expected that if some request is not done, there'd be some way to know that.



    So throwing no errors seems fully within the documentation of how unset works.


    I agree, it does what it says...

    The only 'quirk' is that foo does not go away because the entry is also connected to it via the textvariable option (and this is probably why
    it does not actually go away).


    And also agree, it doesn't do what it says here, it doesn't unset the variable. If it's possible that it's not going to, then it should say so, as long as we're debating whether the manual is fully describing what the command does.

    I stumbled onto this because I have have an in-line wait, that uses after and vwait so as to not lock up things and will even work in a callback (albeit only once) while the main code is also doing a vwait. To accomplish that, it generates temporary
    global variables that it unsets when it's done with them. If there's a better way, I'd be happy to know about that.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Rich@21:1/5 to [email protected] on Sat Oct 15 15:47:14 2022
    et4 <[email protected]> wrote:
    On 10/14/2022 7:14 PM, Rich wrote:
    et4 <[email protected]> wrote:

    Why would you think this? A programming language is not a
    filesystem, and not all file systems follow the Unix filesystem
    model of allowing deletes of open files.

    Hmmm, maybe the principle of least astonishment. I expected that if
    some request is not done, there'd be some way to know that.

    Which is a valid request, but is unrelated to it acting like a unix
    filesystem that allows an open file to have its name deleted, while the
    file lives on until it is closed.

    So throwing no errors seems fully within the documentation of how
    unset works.

    I agree, it does what it says...

    The only 'quirk' is that foo does not go away because the entry is
    also connected to it via the textvariable option (and this is
    probably why it does not actually go away).


    And also agree, it doesn't do what it says here, it doesn't unset the variable. If it's possible that it's not going to, then it should
    say so, as long as we're debating whether the manual is fully
    describing what the command does.

    A documentation edit to clarify that variables that are also bound to -textvariable options of Tk widgets don't unset is reasonably in order.
    Whether that belongs in the unset man page, or the Tk options man page,
    is another choice to make.

    I stumbled onto this because I have have an in-line wait, that uses
    after and vwait so as to not lock up things and will even work in a
    callback (albeit only once) while the main code is also doing a
    vwait. To accomplish that, it generates temporary global variables
    that it unsets when it's done with them.

    Sounds like a fairly standard "don't block the event loop"

    If there's a better way, I'd be happy to know about that.

    1) don't link your event loop semaphore variable to a Tk widget using
    -textvariable

    2) investigate using coroutines

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From [email protected]@21:1/5 to All on Sat Oct 15 15:39:28 2022
    Looking at tkEntry.c in the Tk 8.6.12 source, it appears that entry uses a variable trace to manage the -textvariable. The variable trace calls a C subroutine EntryTextVarProc (in the same file) to trace writes and unsets on the variable. The subroutine
    EntryTextVarProc contains code with the following comment:

    /*
    * If the variable is unset, then immediately recreate it unless the whole
    * interpreter is going away.
    */

    I'm thinking this is a good hint at what is going on.

    Dave B

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From et4@21:1/5 to Rich on Sat Oct 15 12:39:38 2022
    On 10/15/2022 8:47 AM, Rich wrote:
    et4 <[email protected]> wrote:
    On 10/14/2022 7:14 PM, Rich wrote:


    I stumbled onto this because I have have an in-line wait, that uses
    after and vwait so as to not lock up things and will even work in a
    callback (albeit only once) while the main code is also doing a
    vwait. To accomplish that, it generates temporary global variables
    that it unsets when it's done with them.

    Sounds like a fairly standard "don't block the event loop"

    Well, that's what I'm doing. If I just use [after ms] then I can even lock up the console.


    1) don't link your event loop semaphore variable to a Tk widget using
    -textvariable

    It showed up when using a global/namespace variable monitoring tool, originally described by RS in the wiki. When choosing to monitor all globals, some code I was testing used a lot of wait calls so I could see how some Tk actions were working in slow
    motion.

    Suddenly, the monitoring tool was showing the generated globals from the wait calls. It's no biggy, I just thought it was worth mentioning here. The unset manual entry is quite short, and I read it over a couple times before posting. Maybe a ticket is in
    order for the manual.



    2) investigate using coroutines

    I think that's too much trouble to do a simple in-line wait call.

    One of many places I use my wait proc is in an androwish app to remote-control my roku video device. When sending it http commands too quickly it simply drops them. It's far simpler and more readable to just say,

    rsend right; wait 350 ; srend down ; wait 200; rsend ok

    And this is done from a callback after I tap a button.



    On the point about file systems doing it different, this is where I prefer the unix approach over the annoying windows dialog that says, sorry we can't delete that file now, it's in use somewhere, but doesn't tell you where. I get this 2 or 3 times a
    day. It's my most common need of a reboot. I much prefer the "marked for delete on close" used in unix.

    That's what got me looking at the reference counts. I thought that once the entry was destroyed that the count should have dropped to 0 resulting in the final cleanup. I was surprised the ref counts didn't seem to change. But it could have been the
    console fooling me there.


    Dave wrote:

    Looking at tkEntry.c in the Tk 8.6.12 source, it appears that entry uses a variable trace

    Thanks Dave. That makes sense. It's nice that I don't have to cleanup any associations when I destroy an entry. So, I'm a bit surprised that the variable isn't also cleaned up if it's unset. On the other hand, maybe I shouldn't complain, since I don't
    have to deal with an error with the widget.












    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From et4@21:1/5 to [email protected] on Sat Oct 15 19:46:31 2022
    On 10/15/2022 8:39 AM, [email protected] wrote:
    Looking at tkEntry.c in the Tk 8.6.12 source, it appears that entry uses a variable trace to manage the -textvariable. The variable trace calls a C subroutine EntryTextVarProc (in the same file) to trace writes and unsets on the variable. The
    subroutine EntryTextVarProc contains code with the following comment:

    /*
    * If the variable is unset, then immediately recreate it unless the whole
    * interpreter is going away.
    */

    I'm thinking this is a good hint at what is going on.

    Dave B




    Hmmm, after some further thought, I wonder if it might not be better if this code merely disassociated the variable from the entry widget and let the unset stand. Maybe there's something else going on here that made that a difficult choice.

    Good catch Dave!

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From [email protected]@21:1/5 to All on Sun Oct 16 05:40:47 2022
    If you start having problems managing the -textvariable, consider just using the entry get method to read the value. Perhaps in a proc bound to <Return> or maybe <Leave> to do something with the entry value.

    Dave B

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From heinrichmartin@21:1/5 to All on Sun Oct 16 07:28:59 2022
    On Sunday, October 16, 2022 at 4:46:39 AM UTC+2, et4 wrote:
    Hmmm, after some further thought, I wonder if it might not be better if this code merely disassociated the variable from the entry widget and let the unset stand. Maybe there's something else going on here that made that a difficult choice.

    Good catch Dave!

    If I understand correctly, we are looking at Tk's variable trace that is blocking the unset for vwait.
    You could check whether another trace still fires. If so, trigger another variable that vwait would then use.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From et4@21:1/5 to heinrichmartin on Sun Oct 16 11:42:29 2022
    On 10/16/2022 7:28 AM, heinrichmartin wrote:
    On Sunday, October 16, 2022 at 4:46:39 AM UTC+2, et4 wrote:
    Hmmm, after some further thought, I wonder if it might not be better if this code merely disassociated the variable from the entry widget and let the unset stand. Maybe there's something else going on here that made that a difficult choice.

    Good catch Dave!

    If I understand correctly, we are looking at Tk's variable trace that is blocking the unset for vwait.
    You could check whether another trace still fires. If so, trigger another variable that vwait would then use.

    The problem is in my wait code where I generate a new global for each time I do a vwait with an [after] to set the waited on variable. I could probably do an immediate test using [info exist] to see if the variable has been re-incarnated, and just keep
    unsetting it. But then my 4-line wait proc would start getting ugly.

    I'm using the Tk entry as part of a debugging toolset to dynamically display global or namespace static variables. I got the idea from

    Global variable watch & control by RS at

    https://wiki.tcl-lang.org/page/What+debugging+tools+are+available+to+a+Tcl+programmer

    The beauty of RS's technique is in the ease and efficiency of using the Tk -textvariable option.

    Tk is very efficient at this and in my tool's "cruise mode" (variable speed auto-stepping) one can watch variables changing slowly/rapidly while simultaneously see an arrow pointing to the current line of code in a text widget. Spin-boxes control the
    program speed.

    One can watch a variable's tk entry going 1-1000 in just a few seconds, or slow it down as much as desired. This is now combined with my Tasks project up on github. BTW, it works somewhat with methods and class data.


    I think I might send in a ticket on the Tk entry, as it's now pretty clear that unset is not at fault, but rather the entry code which is re-creating the variable that the programmer has specifically unset.

    Trace does this differently - when one unsets a variable that has a trace on it, the trace is automatically removed and the unset stands.

    I think the entry widget should work likewise.

    Thanks again Dave for clearing up this mystery.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Robert Heller@21:1/5 to [email protected] on Sun Oct 16 19:50:17 2022
    At Sun, 16 Oct 2022 11:42:29 -0700 et4 <[email protected]> wrote:


    On 10/16/2022 7:28 AM, heinrichmartin wrote:
    On Sunday, October 16, 2022 at 4:46:39 AM UTC+2, et4 wrote:
    Hmmm, after some further thought, I wonder if it might not be better if this code merely disassociated the variable from the entry widget and let the unset stand. Maybe there's something else going on here that made that a difficult choice.

    Good catch Dave!

    If I understand correctly, we are looking at Tk's variable trace that is blocking the unset for vwait.
    You could check whether another trace still fires. If so, trigger another variable that vwait would then use.

    The problem is in my wait code where I generate a new global for each time I do a vwait with an [after] to set the waited on variable. I could probably do an immediate test using [info exist] to see if the variable has been re-incarnated, and just keep
    unsetting it. But then my 4-line wait proc would start getting ugly.

    If you are generating variables you really need to do two things:

    1) use a *separate* ever increasing counter for each "class" of variables.
    2) use a *seperate* "prefix string" for each "class" of variables.

    If you follow the above rules, there won't be conflicts between -textvariable variables and wait variables. And the code need not be complicated or ugly.


    namespace eval Gensym {
    variable counters [array set {}]

    proc Gensym {class} {
    variable counters
    incr counters($class)
    return [format {%s%05d} $class $counters($class)
    }
    }

    To generate a new variable to wait on:

    Gensym::Gensym wait

    To generate a new variable to bind to an entry:

    Gensym::Gensym entry



    I'm using the Tk entry as part of a debugging toolset to dynamically display global or namespace static variables. I got the idea from

    Global variable watch & control by RS at

    https://wiki.tcl-lang.org/page/What+debugging+tools+are+available+to+a+Tcl+programmer

    The beauty of RS's technique is in the ease and efficiency of using the Tk -textvariable option.

    Tk is very efficient at this and in my tool's "cruise mode" (variable speed auto-stepping) one can watch variables changing slowly/rapidly while simultaneously see an arrow pointing to the current line of code in a text widget. Spin-boxes control the
    program speed.

    One can watch a variable's tk entry going 1-1000 in just a few seconds, or slow it down as much as desired. This is now combined with my Tasks project up on github. BTW, it works somewhat with methods and class data.


    I think I might send in a ticket on the Tk entry, as it's now pretty clear that unset is not at fault, but rather the entry code which is re-creating the variable that the programmer has specifically unset.

    Trace does this differently - when one unsets a variable that has a trace on it, the trace is automatically removed and the unset stands.

    I think the entry widget should work likewise.

    Thanks again Dave for clearing up this mystery.




    --
    Robert Heller -- Cell: 413-658-7953 GV: 978-633-5364
    Deepwoods Software -- Custom Software Services
    http://www.deepsoft.com/ -- Linux Administration Services
    [email protected] -- Webhosting Services

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Schelte@21:1/5 to All on Sun Oct 16 21:16:32 2022
    On 16/10/2022 20:42, et4 wrote:
    I'm using the Tk entry as part of a debugging toolset to dynamically
    display global or namespace static variables.

    Try using a ttk::entry instead.


    Schelte.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From et4@21:1/5 to Schelte on Sun Oct 16 14:09:16 2022
    On 10/16/2022 12:16 PM, Schelte wrote:
    On 16/10/2022 20:42, et4 wrote:
    I'm using the Tk entry as part of a debugging toolset to dynamically display global or namespace static variables.

    Try using a ttk::entry instead.


    Schelte.



    Ahhhh, that seems to work. Interesting though, while the unset does indeed go through, and the widget doesn't seem to care - it blanked the entry, but keeps the variable name, so typing into the entry re-creates the variable.

    I'll have to think about that one, but it's a definite possibility

    thanks

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From et4@21:1/5 to Robert Heller on Sun Oct 16 13:55:53 2022
    On 10/16/2022 12:50 PM, Robert Heller wrote:
    If you follow the above rules, there won't be conflicts between -textvariable variables and wait variables. And the code need not be complicated or ugly.


    namespace eval Gensym {
    variable counters [array set {}]

    proc Gensym {class} {
    variable counters
    incr counters($class)
    return [format {%s%05d} $class $counters($class)
    }
    }

    To generate a new variable to wait on:

    Gensym::Gensym wait

    To generate a new variable to bind to an entry:

    Gensym::Gensym entry



    Thanks, I consider that, here's my simple wait:

    proc wait { ms } {
    set uniq [incr ::__sleep__tmp__counter]
    set ::__sleep__tmp__$uniq 0
    after $ms set ::__sleep__tmp__$uniq 1
    vwait ::__sleep__tmp__$uniq
    unset ::__sleep__tmp__$uniq
    }

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