Search code examples
variablestclprocedures

variables/arrays from tcl procedure


How could i pass some variables/ arrays outside of procedure?

Lets say I've my procedure 'myproc' with inputparameters {a b c d e}, e.g.

myproc {a b c d e} { 
    ... do something
    (calculate arrays, lists and new variables)
}

Inside this procedure I want to calculate an array phiN(1),phiN(2),...phiN(18) out of the variables a-e which itself is a list, e.g.

set phiN(1) [list 1 2 3 4 5 6 7 8 9];

(lets say the values 1-9 had been calculated out of the input variables a-e). And I want to calculate some other parameter alpha and beta

set alpha [expr a+b];
set beta  [expr c+d];

Anyway no I want to pass these new calculated variables outside of my procedure. Compare to matlab I simply would write sg like to get these variables outside of the 'function'.

[phiN,alpha,beta] = myproc{a b c d e}

Has anybody an idea how I can deal in tcl?? Thanks!


Solution

  • There are several options:

    1. Return a list and use lassign outside
      Example:

      proc myproc {a b c d e} {
          set alpha [expr {$a+$b}]
          set beta [expr {$c+$d}]
          return [list $alpha $beta]
      }
      
      lassign [myproc 1 2 3 4 5] alpha beta
      

      This is fine if you return values, but not arrays.

    2. Use upvar and provide the name of the array/variable as argument
      Example:

      proc myproc {phiNVar a b c d e} {
          upvar 1 $phiNVar phiN
          # Now use phiN as local variable
          set phiN(1) [list 1 2 3 4 5 6 7 8 9]
      }
      
      # Usage
      myproc foo 1 2 3 4 5
      foreach i $foo(1) {
           puts $i
      }
      
    3. Use a combination of both
      Example:

      proc myproc {phiNVar a b c d e} {
          uplevel 1 $phiNVar phiN
          set alpha [expr {$a+$b}]
          set beta [expr {$c+$d}]
          set phiN(1) [list 1 2 3 4 5 6 7 8 9]
          return [list $alpha $beta]
      }
      
      lassign [myproc bar 1 2 3 4 5] alpha beta
      foreach i $bar(1) {
           puts $i
      }
      

    Edit: As Donal suggested, is is also possible to return a dict:

    A dict is a Tcl list where the odd elements are the keys and the even elements are the values. You can convert an array to a dict with array get and convert a dict back to an array with array set. You can also use the dict itself.
    Example

         proc myproc {a b c d e} {
            set alpha [expr {$a+$b}]
            set beta [expr {$c+$d}]
            set phiN(1) [list 1 2 3 4 5 6 7 8 9]
            return [list [array get phiN] $alpha $beta]
        }
    
        lassign [myproc 1 2 3 4 5] phiNDict alpha beta
        array set bar $phiNDict
        foreach i $bar(1) {
             puts $i
        }
        # Use the [dict] command to manipulate the dict directly
        puts [dict get $phiNDict 1]
    

    For more ideas (this is about arrays, but could apply to values as well) see this wiki entry.