• can't create namespace variable that refers to procedure variable

    From Luc@21:1/5 to All on Mon Jan 8 15:11:59 2024
    There isn't much about this on Google.

    This doesn't work:

    proc do {} {
    set adjective "good"
    namespace eval ns {
    upvar 1 adjective quality
    puts $quality
    }
    }
    do

    error: bad variable name "quality": can't create namespace variable
    that refers to procedure variable


    I understand the words but not what the message is trying to tell me.

    And then this kludge works:

    proc do {} {
    namespace eval ns {}
    set ns::quality "good"
    namespace eval ns {
    puts $quality
    }
    }
    do

    output: good

    I feel like I just cheated to do somethinhg I was not supposed to.
    What exactly happened here?


    --
    Luc


    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Rich@21:1/5 to Luc on Mon Jan 8 22:35:17 2024
    Luc <luc@sep.invalid> wrote:
    There isn't much about this on Google.

    This doesn't work:

    proc do {} {
    set adjective "good"
    namespace eval ns {
    upvar 1 adjective quality
    puts $quality
    }
    }
    do

    error: bad variable name "quality": can't create namespace variable
    that refers to procedure variable


    I understand the words but not what the message is trying to tell me.

    The message is trying to tell you what it plainly says. You can't do
    what you tried to do.

    upvar is used to refer to variables in the procedure call stack.

    namespaces are not procedures (and do not have a 'position' in the
    procedure call stack).

    upvar (when used in a procedure) makes a variable in the current
    procedure be a reference to another one in the call stack.

    upvar used in a namespace is nonsense, as namespaces exist separate
    from the call stack. You can't create a "reference" in a namespace to
    a local variable in a proc, because while the reference would be valid
    while the current proc invocation exists, the moment the proc returns,
    the 'reference' in the namespace would be pointing to a variable that
    no longer exists (proc locals only exist while the proc is running,
    once the proc returns, all of the proc locals go away).

    And then this kludge works:

    proc do {} {
    namespace eval ns {}
    set ns::quality "good"
    namespace eval ns {
    puts $quality
    }
    }
    do

    That's not a kluge, that is one valid way to create, and set, a
    variable in a namespace.

    I feel like I just cheated to do somethinhg I was not supposed to.
    What exactly happened here?

    You tried to do something that is nonsensical. upvar connects together
    local variables in different procs. Namespaces are not procs,
    therefore, trying to connect a namespace variable to a proc local is
    nonsense.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Luc@21:1/5 to Rich on Mon Jan 8 20:35:33 2024
    On Mon, 8 Jan 2024 22:35:17 -0000 (UTC), Rich wrote:

    You tried to do something that is nonsensical. upvar connects together
    local variables in different procs. Namespaces are not procs,
    therefore, trying to connect a namespace variable to a proc local is >nonsense.


    Thank you.

    Your explanation makes a lot of sense, but can you really blame me for
    the mixup when there is a 'namespace upvar' command? Does that command
    qualify as 'nonsense' too?


    --
    Luc


    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Rich@21:1/5 to Luc on Tue Jan 9 01:49:58 2024
    Luc <luc@sep.invalid> wrote:
    On Mon, 8 Jan 2024 22:35:17 -0000 (UTC), Rich wrote:

    You tried to do something that is nonsensical. upvar connects
    together local variables in different procs. Namespaces are not
    procs, therefore, trying to connect a namespace variable to a proc
    local is nonsense.


    Thank you.

    Your explanation makes a lot of sense, but can you really blame me for
    the mixup when there is a 'namespace upvar' command? Does that command qualify as 'nonsense' too?

    No, because it is defined as linking namespace variables into the
    current proc as locals for that proc.

    Both are for creating proc local variables that link to other places.

    You were trying to create a "namespace variable" that was a link
    referring to a proc local variable. Which link would (if it could be
    created in the first place) become invalid as soon as the proc returns.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Luc@21:1/5 to Rich on Tue Jan 9 02:49:31 2024
    On Tue, 9 Jan 2024 01:49:58 -0000 (UTC), Rich wrote:

    No, because it is defined as linking namespace variables into the
    current proc as locals for that proc.


    OK. Though still weird that someone might prefer

    namespace upvar ns var localvar
    set localvar 125

    to a much simpler

    set ns::var 125


    Anyway, I wish I had used namespaces sooner. I spent so much time
    worrying about keeping track of the tabs, like

    set tabID [dict get $::FlowControl ActiveTabID]

    then using tons of [dict get] here and there to access multiple values
    in complicated ways.

    Now I just get the ID then run everything inside

    namespace eval $tabID {}

    and everything just works with much simpler syntax and all the context separation I always meant in the first place. Even that thread thing
    is working with simpler code.


    --
    Luc


    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Rich@21:1/5 to Luc on Tue Jan 9 20:10:54 2024
    Luc <luc@sep.invalid> wrote:
    On Tue, 9 Jan 2024 01:49:58 -0000 (UTC), Rich wrote:

    No, because it is defined as linking namespace variables into the
    current proc as locals for that proc.


    OK. Though still weird that someone might prefer

    namespace upvar ns var localvar
    set localvar 125

    to a much simpler

    set ns::var 125


    Anyway, I wish I had used namespaces sooner. I spent so much time
    worrying about keeping track of the tabs, like

    set tabID [dict get $::FlowControl ActiveTabID]

    then using tons of [dict get] here and there to access multiple values
    in complicated ways.

    Now I just get the ID then run everything inside

    namespace eval $tabID {}

    and everything just works with much simpler syntax and all the context separation I always meant in the first place. Even that thread thing
    is working with simpler code.

    You've simply created a "poor man's object".

    I.e., you've recreated "objects" from the existing primitives, but
    without some of the niceties that tcloo provides for objects.

    Each tab has a backing 'object' and that 'object' holds all the state
    data for the tab (which is one of the benefits of objects, easier
    'separation of concerns' like this).

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From et99@21:1/5 to Rich on Tue Jan 9 13:01:46 2024
    On 1/9/2024 12:10 PM, Rich wrote:
    Luc <luc@sep.invalid> wrote:
    On Tue, 9 Jan 2024 01:49:58 -0000 (UTC), Rich wrote:

    No, because it is defined as linking namespace variables into the
    current proc as locals for that proc.


    OK. Though still weird that someone might prefer

    namespace upvar ns var localvar
    set localvar 125

    to a much simpler

    set ns::var 125


    Anyway, I wish I had used namespaces sooner. I spent so much time
    worrying about keeping track of the tabs, like

    set tabID [dict get $::FlowControl ActiveTabID]

    then using tons of [dict get] here and there to access multiple values
    in complicated ways.

    Now I just get the ID then run everything inside

    namespace eval $tabID {}

    and everything just works with much simpler syntax and all the context
    separation I always meant in the first place. Even that thread thing
    is working with simpler code.

    You've simply created a "poor man's object".

    I.e., you've recreated "objects" from the existing primitives, but
    without some of the niceties that tcloo provides for objects.

    Each tab has a backing 'object' and that 'object' holds all the state
    data for the tab (which is one of the benefits of objects, easier
    'separation of concerns' like this).

    Ashok's book has a very good introduction to tclOO. An online draft chapter can be found here:

    https://www.magicsplat.com/articles/oo.html

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