tcl use variable in namespace name

Go To StackoverFlow.com

1

Tcl 8.4.

I have this namespace tree:

namespace eval menu_tree {

    #--------------------------------------------------------------------------
    ## Main Menu
    namespace eval main_menu {
        variable title "Main Menu"
    }

    #--------------------------------------------------------------------------
    ## Setup Menu
    namespace eval setup_menu {
        variable title "Show Setup Information"
    }

    #--------------------------------------------------------------------------
    ## Help Menu
    namespace eval help_menu {
        variable title "Show Help Information"
    }
}

The idea was to have a function like this:

proc print_title {menu} {
    puts $menu::title
}

This would work fine with global variables. However, from what I can find, using '$' with namespace names is required. I have tried to find the answer on the web, but nothing came up. Does anyone know how to do it, and if it is even possible?

Thank you, -Ilya.

2012-04-03 20:06
by ilya1725


4

Well, the key approach here is to keep in mind that "the original Tcl" did not have that "$" syntactic sugar at all. The original way to get the contents of a variable is a one-argument call to set:

set foo bar ;# sets variable "foo" to contain the value "bar"
puts [set foo] ;# prints the value contained in variabe "foo"

Hence you'll probably should use something like

proc print_title {menu} {
    puts [set ${menu}::title]
}

so that ${menu}::title expands to the name of a variable then set retrieves the value of that variable.

Note the usage of curly braces around the word "menu"--without them, Tcl would try to dereference a variable named "menu::title" which is probably not what you intended.

Another thing to observe is that the behaviour of print_title highly depends on the contents of the "menu" argument: after it's expanded, the set command must see a string which it should be able to resolve, and this is subject to a set of rules. It's hard to get further advice until more details is known though.

Refer to this question for more info about on that $ vs set topic.

2012-04-03 21:04
by kostix
${menu} was the trick. The code that finally worked is this: puts [set menu_tree::${menu}::title]ilya1725 2012-04-04 01:17
If you're manipulating the same variable twice in one procedure, it's going to be easier to use upvar to alias it to a local variable name. upvar menu_tree::${menu}::title fruitbat; puts $fruitbatDonal Fellows 2012-04-04 07:10