• How to read a namespace variable when using variable name in namespace?

    From johan.kuuse@gmail.com@user6026@newsgrouper.org.invalid to comp.lang.tcl on Mon Aug 25 18:56:39 2025
    From Newsgroup: comp.lang.tcl


    Hi,

    In the example code below, I try to access a proc and a variable in a namespace,
    when using a variable for the namespace name itself.

    Calling the namespace proc, or *updating* the namespace variable works ok. What bites me is how to *read* the namespace variable.

    As shown in the code below, I can read the namespace variable by combining
    it with the 'set' command.
    My question is if there is another way to read the namespace variable.


    Sample code:
    # --------------------------------------------------------------------------------
    # The example namespace
    namespace eval myns {
    variable myvar 42
    proc myproc {} {
    return "Hello world!"
    }
    }

    # Call namespace proc using string literal 'myns'
    puts "myns::myproc = [myns::myproc]"
    puts "::myns::myproc = [::myns::myproc]"

    # Read namespace variable using string literal 'myns'
    puts "myns::myvar = $myns::myvar"
    puts "::myns::myvar = $::myns::myvar"

    set NS_NAME myns

    # Call namespace proc using string variable '$NS_NAME' - WORKS
    puts "NS_NAME::myproc = [${NS_NAME}::myproc]"
    puts "::NS_NAME::myproc = [::${NS_NAME}::myproc]"

    # Read namespace variable using only string variable '$NS_NAME' - FAILS
    puts "NS_NAME::myvar = ${NS_NAME}::myvar"
    puts "::NS_NAME::myvar = ::${NS_NAME}::myvar"

    # Read namespace variable using 'set' and string variable '$NS_NAME' - WORKS puts "NS_NAME::myvar = [set ${NS_NAME}::myvar]"
    puts "::NS_NAME::myvar = [set ::${NS_NAME}::myvar]"

    # Update namespace variable using only string variable '$NS_NAME' - WORKS
    set ${NS_NAME}::myvar 43

    # Read updated variable
    puts "myns::myvar = $myns::myvar"
    puts "NS_NAME::myvar = ${NS_NAME}::myvar"; # FAILS
    puts "NS_NAME::myvar = [set ${NS_NAME}::myvar]"; # WORKS
    # --------------------------------------------------------------------------------

    Best Regards,
    Johan Kuuse
    --- Synchronet 3.21a-Linux NewsLink 1.2
  • From saito@saitology9@gmail.com to comp.lang.tcl on Mon Aug 25 15:20:48 2025
    From Newsgroup: comp.lang.tcl

    On 8/25/2025 2:56 PM, johan.kuuse@gmail.com wrote:

    Hi,

    In the example code below, I try to access a proc and a variable in a namespace,
    when using a variable for the namespace name itself.

    Calling the namespace proc, or *updating* the namespace variable works ok. What bites me is how to *read* the namespace variable.

    As shown in the code below, I can read the namespace variable by combining
    it with the 'set' command.
    My question is if there is another way to read the namespace variable.

    ...

    # Read namespace variable using only string variable '$NS_NAME' - FAILS
    puts "NS_NAME::myvar = ${NS_NAME}::myvar"
    puts "::NS_NAME::myvar = ::${NS_NAME}::myvar"


    Not sure if it is the best way, but a couple of solutions:

    # this works
    % puts "::NS_NAME::myvar = [namespace eval ::$NS_NAME {set ::${NS_NAME}::myvar}]"

    # this works
    % puts "::NS_NAME::myvar = [eval {set ::${NS_NAME}::myvar}]"


    --- Synchronet 3.21a-Linux NewsLink 1.2
  • From Harald Oehlmann@wortkarg3@yahoo.com to comp.lang.tcl on Mon Aug 25 21:33:51 2025
    From Newsgroup: comp.lang.tcl

    Am 25.08.2025 um 20:56 schrieb johan.kuuse@gmail.com:
    Hi,

    In the example code below, I try to access a proc and a variable in a namespace,
    when using a variable for the namespace name itself.

    Calling the namespace proc, or*updating* the namespace variable works ok. What bites me is how to*read* the namespace variable.

    As shown in the code below, I can read the namespace variable by combining
    it with the 'set' command.
    My question is if there is another way to read the namespace variable.


    Sample code:
    # --------------------------------------------------------------------------------
    # The example namespace
    namespace eval myns {
    variable myvar 42
    proc myproc {} {
    return "Hello world!"
    }
    }

    # Call namespace proc using string literal 'myns'
    puts "myns::myproc = [myns::myproc]"
    puts "::myns::myproc = [::myns::myproc]"

    # Read namespace variable using string literal 'myns'
    puts "myns::myvar = $myns::myvar"
    puts "::myns::myvar = $::myns::myvar"

    set NS_NAME myns

    What about this:

    % set ::${NS_NAME}::myvar
    42
    % ::${NS_NAME}::myproc
    Hello world!

    To get access, you may also enjoy "namespace which":
    % set varName [namespace eval $NS_NAME {namespace which -variable myvar}] ::myns::myvar
    % set $varName
    42

    % set cmdName [namespace eval $NS_NAME {namespace which -command myproc}] ::myns::myproc
    % $cmdName
    Hello world!

    Sorry, I did not understand all your examples, but this is IMHO
    conformant to your question.

    Take care,
    Harald

    --- Synchronet 3.21a-Linux NewsLink 1.2
  • From johan.kuuse@gmail.com@user6026@newsgrouper.org.invalid to comp.lang.tcl on Mon Aug 25 20:34:07 2025
    From Newsgroup: comp.lang.tcl


    Harald Oehlmann <wortkarg3@yahoo.com> posted:

    Am 25.08.2025 um 20:56 schrieb johan.kuuse@gmail.com:
    Hi,

    In the example code below, I try to access a proc and a variable in a namespace,
    when using a variable for the namespace name itself.

    Calling the namespace proc, or*updating* the namespace variable works ok. What bites me is how to*read* the namespace variable.

    As shown in the code below, I can read the namespace variable by combining it with the 'set' command.
    My question is if there is another way to read the namespace variable.


    Sample code:
    # --------------------------------------------------------------------------------
    # The example namespace
    namespace eval myns {
    variable myvar 42
    proc myproc {} {
    return "Hello world!"
    }
    }

    # Call namespace proc using string literal 'myns'
    puts "myns::myproc = [myns::myproc]"
    puts "::myns::myproc = [::myns::myproc]"

    # Read namespace variable using string literal 'myns'
    puts "myns::myvar = $myns::myvar"
    puts "::myns::myvar = $::myns::myvar"

    set NS_NAME myns

    What about this:

    % set ::${NS_NAME}::myvar
    42
    % ::${NS_NAME}::myproc
    Hello world!

    To get access, you may also enjoy "namespace which":
    % set varName [namespace eval $NS_NAME {namespace which -variable myvar}] ::myns::myvar
    % set $varName
    42

    % set cmdName [namespace eval $NS_NAME {namespace which -command myproc}] ::myns::myproc
    % $cmdName
    Hello world!

    Sorry, I did not understand all your examples, but this is IMHO
    conformant to your question.

    Take care,
    Harald


    Thank you both for your answers.

    With my examples, I tried to show that *setting* a namespace variable can be done
    using basically the same syntax with either using a string literal ('myns')
    or a variable ($NS_NAME):

    set myns::myvar 42
    set ${NS_NAME}::myvar 42

    And *getting* a namespace variable when using a string literal ('myns') is
    also straight-forward:

    puts "myns::myvar = $myns::myvar"

    Anyhow, *getting* a namespace variable when using a variable ($NS_NAME)
    seems to require either 'set', 'namespace eval' or 'namespace which' (or a combination):

    puts "myns::myvar = [set ${NS_NAME}::myvar]"
    puts "myns::myvar = [eval {set ::${NS_NAME}::myvar}]"
    puts "myns::myvar = [set [namespace eval ::$NS_NAME {set ::${NS_NAME}::myvar}]" puts "myns::myvar = [set [namespace eval $NS_NAME {namespace which -variable myvar}]]

    My "real" question is if there is a "shorter" form for reading the variable.

    BR,
    Johan
    --- Synchronet 3.21a-Linux NewsLink 1.2
  • From Schelte@nospam@wanadoo.nl to comp.lang.tcl on Mon Aug 25 22:56:22 2025
    From Newsgroup: comp.lang.tcl

    On 25/08/2025 21:20, saito wrote:
    # this works
    % puts "::NS_NAME::myvar-a = [namespace eval ::$NS_NAME {set ::${NS_NAME}::myvar}]"

    It works, but it is very convoluted. Within the namespace there is no
    need to use a fully qualified variable name. So you could just do:

    % puts "::NS_NAME::myvar = [namespace eval $NS_NAME {set myvar}]"

    # this works
    % puts "::NS_NAME::myvar-a = [eval {set ::${NS_NAME}::myvar}]"
    Here, there is no need for the eval:

    % puts "::NS_NAME::myvar = [set ::${NS_NAME}::myvar]"

    Which in fact is one of the options the OP already mentioned.


    Schelte

    --- Synchronet 3.21a-Linux NewsLink 1.2
  • From Schelte@nospam@wanadoo.nl to comp.lang.tcl on Mon Aug 25 23:01:44 2025
    From Newsgroup: comp.lang.tcl

    On 25/08/2025 22:34, johan.kuuse@gmail.com wrote:
    puts "myns::myvar = [set [namespace eval ::$NS_NAME {set ::${NS_NAME}::myvar}]"
    puts "myns::myvar = [set [namespace eval $NS_NAME {namespace which -variable myvar}]]

    As mentioned in my other response, that can be simplified to:

    puts "myns::myvar = [namespace eval $NS_NAME {set myvar}"

    My "real" question is if there is a "shorter" form for reading the variable.

    Depending on how much you need to use the variable, you can do:

    namespace upvar $NS_NAME myvar mynsvar
    puts "myns::myvar = $mynsvar"
    set mynsvar 43
    # Or set ${NS_NAME}::myvar 43
    puts "myns::myvar = $mynsvar"


    Schelte

    --- Synchronet 3.21a-Linux NewsLink 1.2
  • From saito@saitology9@gmail.com to comp.lang.tcl on Mon Aug 25 19:08:49 2025
    From Newsgroup: comp.lang.tcl

    On 8/25/2025 4:56 PM, Schelte wrote:

    It works, but it is very convoluted. Within the namespace there is no
    need to use a fully qualified variable name. So you could just do:

    ...

    Which in fact is one of the options the OP already mentioned.


    You are right. TBH, I didn't read the whole article before I replied;
    and that is my fault. I looked for a way to delete the post right away
    but that is not possible it seems.

    In any case, here is my recommended and perhaps the shortest solution
    that works for any variable, with an explicit or implied namespace. You
    can change the ordering of the variable and ns arguments and you can
    have a similar proc for setting it too:

    % proc nsv {var {ns {}}} { return [namespace eval ::[string trimright
    $ns ::] [list set $var]] }

    % set NS_NAME myns
    myns


    % nsv myvar $NS_NAME
    42


    % puts "::NS_NAME::myvar = [nsv myvar $NS_NAME]"
    ::NS_NAME::myvar = 42


    % set xyz 100


    % nsv xyz
    100




    --- Synchronet 3.21a-Linux NewsLink 1.2
  • From Harald Oehlmann@wortkarg3@yahoo.com to comp.lang.tcl on Tue Aug 26 09:22:43 2025
    From Newsgroup: comp.lang.tcl

    Am 25.08.2025 um 22:34 schrieb johan.kuuse@gmail.com:

    Harald Oehlmann <wortkarg3@yahoo.com> posted:

    Am 25.08.2025 um 20:56 schrieb johan.kuuse@gmail.com:
    Hi,

    In the example code below, I try to access a proc and a variable in a namespace,
    when using a variable for the namespace name itself.

    Calling the namespace proc, or*updating* the namespace variable works ok. >>> What bites me is how to*read* the namespace variable.

    As shown in the code below, I can read the namespace variable by combining >>> it with the 'set' command.
    My question is if there is another way to read the namespace variable.


    Sample code:
    # --------------------------------------------------------------------------------
    # The example namespace
    namespace eval myns {
    variable myvar 42
    proc myproc {} {
    return "Hello world!"
    }
    }

    # Call namespace proc using string literal 'myns'
    puts "myns::myproc = [myns::myproc]"
    puts "::myns::myproc = [::myns::myproc]"

    # Read namespace variable using string literal 'myns'
    puts "myns::myvar = $myns::myvar"
    puts "::myns::myvar = $::myns::myvar"

    set NS_NAME myns

    What about this:

    % set ::${NS_NAME}::myvar
    42
    % ::${NS_NAME}::myproc
    Hello world!

    To get access, you may also enjoy "namespace which":
    % set varName [namespace eval $NS_NAME {namespace which -variable myvar}] >> ::myns::myvar
    % set $varName
    42

    % set cmdName [namespace eval $NS_NAME {namespace which -command myproc}]
    ::myns::myproc
    % $cmdName
    Hello world!

    Sorry, I did not understand all your examples, but this is IMHO
    conformant to your question.

    Take care,
    Harald


    Thank you both for your answers.

    With my examples, I tried to show that *setting* a namespace variable can be done
    using basically the same syntax with either using a string literal ('myns') or a variable ($NS_NAME):

    set myns::myvar 42
    set ${NS_NAME}::myvar 42

    And *getting* a namespace variable when using a string literal ('myns') is also straight-forward:

    puts "myns::myvar = $myns::myvar"

    Anyhow, *getting* a namespace variable when using a variable ($NS_NAME)
    seems to require either 'set', 'namespace eval' or 'namespace which' (or a combination):

    puts "myns::myvar = [set ${NS_NAME}::myvar]"
    puts "myns::myvar = [eval {set ::${NS_NAME}::myvar}]"
    puts "myns::myvar = [set [namespace eval ::$NS_NAME {set ::${NS_NAME}::myvar}]"
    puts "myns::myvar = [set [namespace eval $NS_NAME {namespace which -variable myvar}]]

    My "real" question is if there is a "shorter" form for reading the variable.

    BR,
    Johan
    Well, you need two rounds of variable resolution.
    For me, the following two are my favorites:
    If the variable should be accessed from the outside as value:
    [set ${NS_NAME}::myvar]
    If something should be done with the variable, this might be cleaner:
    namespace eval $NS_NAME {do something with $myvar}

    You may also consider using an object with tcloo. THen, you have more
    options here.
    Also, an access function is common.
    Normally, you don't want to expose the inside of a namespace to the
    outside.If you "just" want a variable store, dicts and arrays may be
    helpful.

    Take care,
    Harald
    --- Synchronet 3.21a-Linux NewsLink 1.2
  • From johan.kuuse@gmail.com@user6026@newsgrouper.org.invalid to comp.lang.tcl on Wed Aug 27 18:13:29 2025
    From Newsgroup: comp.lang.tcl


    Harald Oehlmann <wortkarg3@yahoo.com> posted:

    Am 25.08.2025 um 22:34 schrieb johan.kuuse@gmail.com:

    Harald Oehlmann <wortkarg3@yahoo.com> posted:

    Am 25.08.2025 um 20:56 schrieb johan.kuuse@gmail.com:
    Hi,

    In the example code below, I try to access a proc and a variable in a namespace,
    when using a variable for the namespace name itself.

    Calling the namespace proc, or*updating* the namespace variable works ok. >>> What bites me is how to*read* the namespace variable.

    As shown in the code below, I can read the namespace variable by combining
    it with the 'set' command.
    My question is if there is another way to read the namespace variable. >>>

    Sample code:
    # --------------------------------------------------------------------------------
    # The example namespace
    namespace eval myns {
    variable myvar 42
    proc myproc {} {
    return "Hello world!"
    }
    }

    # Call namespace proc using string literal 'myns'
    puts "myns::myproc = [myns::myproc]"
    puts "::myns::myproc = [::myns::myproc]"

    # Read namespace variable using string literal 'myns'
    puts "myns::myvar = $myns::myvar"
    puts "::myns::myvar = $::myns::myvar"

    set NS_NAME myns

    What about this:

    % set ::${NS_NAME}::myvar
    42
    % ::${NS_NAME}::myproc
    Hello world!

    To get access, you may also enjoy "namespace which":
    % set varName [namespace eval $NS_NAME {namespace which -variable myvar}] >> ::myns::myvar
    % set $varName
    42

    % set cmdName [namespace eval $NS_NAME {namespace which -command myproc}] >> ::myns::myproc
    % $cmdName
    Hello world!

    Sorry, I did not understand all your examples, but this is IMHO
    conformant to your question.

    Take care,
    Harald


    Thank you both for your answers.

    With my examples, I tried to show that *setting* a namespace variable can be done
    using basically the same syntax with either using a string literal ('myns') or a variable ($NS_NAME):

    set myns::myvar 42
    set ${NS_NAME}::myvar 42

    And *getting* a namespace variable when using a string literal ('myns') is also straight-forward:

    puts "myns::myvar = $myns::myvar"

    Anyhow, *getting* a namespace variable when using a variable ($NS_NAME) seems to require either 'set', 'namespace eval' or 'namespace which' (or a combination):

    puts "myns::myvar = [set ${NS_NAME}::myvar]"
    puts "myns::myvar = [eval {set ::${NS_NAME}::myvar}]"
    puts "myns::myvar = [set [namespace eval ::$NS_NAME {set ::${NS_NAME}::myvar}]"
    puts "myns::myvar = [set [namespace eval $NS_NAME {namespace which -variable myvar}]]

    My "real" question is if there is a "shorter" form for reading the variable.

    BR,
    Johan
    Well, you need two rounds of variable resolution.
    For me, the following two are my favorites:
    If the variable should be accessed from the outside as value:
    [set ${NS_NAME}::myvar]
    If something should be done with the variable, this might be cleaner: namespace eval $NS_NAME {do something with $myvar}

    You may also consider using an object with tcloo. THen, you have more options here.
    Also, an access function is common.
    Normally, you don't want to expose the inside of a namespace to the outside.If you "just" want a variable store, dicts and arrays may be helpful.

    Take care,
    Harald


    Yes, you are right, I probably don't want to expose the inside of a namespace to the outside.

    I have also learned that using a variable for namespace names may not be such a brillant idea that I first thought of.
    Sticking to hardcoded names makes the code cleaner, IMHO.

    Thanks again for all input.
    --- Synchronet 3.21a-Linux NewsLink 1.2
  • From Rich@rich@example.invalid to comp.lang.tcl on Wed Aug 27 21:48:18 2025
    From Newsgroup: comp.lang.tcl

    johan.kuuse@gmail.com <user6026@newsgrouper.org.invalid> wrote:

    Yes, you are right, I probably don't want to expose the inside of a namespace to the outside.

    I have also learned that using a variable for namespace names may not
    be such a brillant idea that I first thought of. Sticking to
    hardcoded names makes the code cleaner, IMHO.

    Unless you are planning on building a generic "namespace inspector"
    that has to work for any given namespace, it is often best to simply
    use hard coded namespaces. Make the names meaningful to your codebase
    and don't worry about trying to "fake" something like a C pointer to
    get access to the internals.
    --- Synchronet 3.21a-Linux NewsLink 1.2
  • From Harald Oehlmann@wortkarg3@yahoo.com to comp.lang.tcl on Thu Aug 28 10:30:05 2025
    From Newsgroup: comp.lang.tcl

    Am 27.08.2025 um 20:13 schrieb johan.kuuse@gmail.com:

    Harald Oehlmann <wortkarg3@yahoo.com> posted:

    Am 25.08.2025 um 22:34 schrieb johan.kuuse@gmail.com:

    Harald Oehlmann <wortkarg3@yahoo.com> posted:

    Am 25.08.2025 um 20:56 schrieb johan.kuuse@gmail.com:
    Hi,

    In the example code below, I try to access a proc and a variable in a namespace,
    when using a variable for the namespace name itself.

    Calling the namespace proc, or*updating* the namespace variable works ok. >>>>> What bites me is how to*read* the namespace variable.

    As shown in the code below, I can read the namespace variable by combining
    it with the 'set' command.
    My question is if there is another way to read the namespace variable. >>>>>

    Sample code:
    # --------------------------------------------------------------------------------
    # The example namespace
    namespace eval myns {
    variable myvar 42
    proc myproc {} {
    return "Hello world!"
    }
    }

    # Call namespace proc using string literal 'myns'
    puts "myns::myproc = [myns::myproc]"
    puts "::myns::myproc = [::myns::myproc]"

    # Read namespace variable using string literal 'myns'
    puts "myns::myvar = $myns::myvar"
    puts "::myns::myvar = $::myns::myvar"

    set NS_NAME myns

    What about this:

    % set ::${NS_NAME}::myvar
    42
    % ::${NS_NAME}::myproc
    Hello world!

    To get access, you may also enjoy "namespace which":
    % set varName [namespace eval $NS_NAME {namespace which -variable myvar}] >>>> ::myns::myvar
    % set $varName
    42

    % set cmdName [namespace eval $NS_NAME {namespace which -command myproc}] >>>> ::myns::myproc
    % $cmdName
    Hello world!

    Sorry, I did not understand all your examples, but this is IMHO
    conformant to your question.

    Take care,
    Harald


    Thank you both for your answers.

    With my examples, I tried to show that *setting* a namespace variable can be done
    using basically the same syntax with either using a string literal ('myns') >>> or a variable ($NS_NAME):

    set myns::myvar 42
    set ${NS_NAME}::myvar 42

    And *getting* a namespace variable when using a string literal ('myns') is >>> also straight-forward:

    puts "myns::myvar = $myns::myvar"

    Anyhow, *getting* a namespace variable when using a variable ($NS_NAME)
    seems to require either 'set', 'namespace eval' or 'namespace which' (or a combination):

    puts "myns::myvar = [set ${NS_NAME}::myvar]"
    puts "myns::myvar = [eval {set ::${NS_NAME}::myvar}]"
    puts "myns::myvar = [set [namespace eval ::$NS_NAME {set ::${NS_NAME}::myvar}]"
    puts "myns::myvar = [set [namespace eval $NS_NAME {namespace which -variable myvar}]]

    My "real" question is if there is a "shorter" form for reading the variable.

    BR,
    Johan
    Well, you need two rounds of variable resolution.
    For me, the following two are my favorites:
    If the variable should be accessed from the outside as value:
    [set ${NS_NAME}::myvar]
    If something should be done with the variable, this might be cleaner:
    namespace eval $NS_NAME {do something with $myvar}

    You may also consider using an object with tcloo. THen, you have more
    options here.
    Also, an access function is common.
    Normally, you don't want to expose the inside of a namespace to the
    outside.If you "just" want a variable store, dicts and arrays may be
    helpful.

    Take care,
    Harald


    Yes, you are right, I probably don't want to expose the inside of a namespace to the outside.

    I have also learned that using a variable for namespace names may not be such a brillant idea that I first thought of.
    Sticking to hardcoded names makes the code cleaner, IMHO.

    Thanks again for all input.

    There is nothing wrong wrong your approach.

    Double resolution be the "set" command looks ugly (there is nothing
    set), but often a great tool. It is usable at any time where you have a variable name (or part of it) in a variable.

    But a tcl pbject might be a point to look to.

    Take care,
    Harald
    --- Synchronet 3.21a-Linux NewsLink 1.2