yorgo
yorgo

Reputation: 507

Tcl : pass all variables from main to procedure

In my tcl script there is a part of the code that is repeated a lot, so I want to make a procedure out of it.

The thing is this part uses dozens of variables, which I would like to avoid passing as arguments to the procedure. Is there a way to make all variables visible to the procedure? (Practically I want the "main" to branch to the procedure like a "goto" and then return and continue in main).

Edited: It does not need to be a procedure, feel free to suggest other ways to do this. The important part is not need to declare all variables/arguments passing from main to the function/procedure.

Example:

 proc dummy_proc {} {
 set var1 $var2
 set var2 $var3
 }

 set var2 2
 set var3 3
 dummy_proc 
 puts "$var1 $var2"
 # should print "2 3"

Upvotes: 0

Views: 2252

Answers (2)

user2141046
user2141046

Reputation: 912

Use global

proc dummy_proc {} {  
  global var2 var3  
  set var1 $var2  
  set var2 $var3  
}

set var2 2  
set var3 3  
dummy_proc   
puts "$var1 $var2"  

If you have a lot of globals you want to pass, you can use some foreach, but than you'll have to have a way to find them all.
e.g. all globals are called GLOBAL_<SOMEARG>

proc dummy_proc {} { 
  foreach glb [info globals GLOBAL_*] { 
    global $glb 
  } 
  ... 
}

Upvotes: 0

slebetman
slebetman

Reputation: 114014

This is possible but generally not advisable due to the fact that it can make code harder to read (there's no direct indication where the variables come from or how variable values suddenly change). However in some cases this can reduce repetitive code.

Use upvar (https://www.tcl.tk/man/tcl8.6/TclCmd/upvar.htm):

proc dummy_proc {} {
    upvar var1 v1
    upvar var2 v2
    upvar var3 v3

    set v1 $v2
    set v2 $v3
}

What upvar does is create a variable in local scope that references another variable in the caller's scope.

Alternatively you can also try using uplevel (https://www.tcl.tk/man/tcl8.6/TclCmd/uplevel.htm):

proc dummy_proc {} {
    uplevel {
        set var1 $var2
        set var2 $var3
    }
}

What uplevel does is similar to upvar but instead of creating variable references it actually executes code in the caller's scope. It's as if you temporarily go back to the caller function without returning, execute some code and come back. Because you execute code in the caller's scope all variables visible in the caller's scope is visible in the code you upleveled. Uplevel behaves almost like a macro instead of a function.

Upvotes: 3

Related Questions