You are here: Surpac Concepts > Macros > TCL > TCL procedures
GEOVIA Surpac

TCL Procedures

Procedures in Tcl serve much the same purpose as functions in C. They may take arguments, and may return values. The basic syntax for defining a procedure is:

proc name argList body

After a procedure is created, it is considered to be a command, just like any other built-in Tcl command. As such, it may be called using its name, followed by a value for each of its arguments. The return value from a procedure is equivalent to the result of a built-in Tcl command. Thus, command substitution can be used to substitute the return value of a procedure into another expression.

By default, the return value from a procedure is the result of the last command in its body. However, to return another value, the return command may be used. If an argument is given to the return command, then the value of this argument becomes the result of the procedure. The return command may be used anywhere in the body of the procedure, causing the procedure to exit immediately.

Example 5.1: Simple procedure to add to numbers and determine absolute value of a number

proc sum_proc {a b} {
    return [expr $a + $b]
}
proc magnitude {num} {
    if {$num > 0} {
        return $num
    } 
    set num [expr $num * (-1)]
    return $num
}
set num1 12
set num2 14
set sum [sum_proc $num1 $num2]
puts "The sum is $sum"
puts "The magnitude of 3 is [magnitude 3]"
puts "The magnitude of -2 is [magnitude -2]"
      

Output:

The sum is 26

The magnitude of 3 is 3

The magnitude of -2 is 2

This example first creates two procedures, "sum_proc" and "magnitude". "sum_proc" takes two arguments, and simply returns the value of their sum. "magnitude" returns the absolute value of a number. After the procedure definitions, three global variables are created. The last of these, "sum" is assigned the return value of the procedure "sum_proc", called with the values of the variables "num1" and "num2" as arguments. The "magnitude" procedure is then called twice, first with "3" as an argument, then with "-2".

The "sum_proc" procedure uses the expr command to calculate the sum of its arguments. The result of the expr command is substituted into the return statement, making it the return value for the procedure.

The "magnitude" procedure makes use of an if-statement to take different actions, depending on the sign of its argument. If the number is positive, its value is returned, and the procedure exits immediately, skipping all the rest of its code. Otherwise, the number is multiplied by -1 to obtain its magnitude, and this value is returned. The same effect could be achieved by moving the statement that multiplies the value by -1 into an else-clause, but the purpose of this example was to illustrate the use of the return statement at several locations within a procedure.

Inside the body of a procedure, new variables may be created with the set command as normal. However, these variables will be local to the procedure, and will no longer be accessible once the procedure returns. If access to global variables is needed inside a procedure, these may be accessed by means of the global keyword, as described in Example 5.2.

Example 5.2: Use of global variables inside procedures

proc dumb_proc {} {
    set myvar 4
    puts "The value of the local variable is $myvar"
    global myglobalvar
    puts "The value of the global variable is $myglobalvar"
}
set myglobalvar 79
dumb_proc
      

Output:

The value of the local variable is 4

The value of the global variable is 79

The procedure "dumb_proc" achieves no special purpose, and is simply designed to illustrate the use of the global keyword to access global variables. It takes no arguments, and as such its argument list is empty. Note that even though the procedure takes no arguments, the empty list structure must still be included.

The procedure first creates a local variable, "myvar", sets its value to "4", and then displays it. Then it uses the global keyword to gain access to a global variable named "myglobalvar". The value of this global variable is then printed.

After the procedure definition, a global variable "myglobalvar" is created, and assigned a value of "79". The procedure "dumb_proc" is then called, resulting in the output shown above.

Example 5.3: Use of upvar to modify argument values

#
# scale x and y coordinates by a scalefactor
#
proc scale {xvalue yvalue scalefactor} {
  upvar $xvalue x
  upvar $yvalue y
  set x [expr $x * $scalefactor]
  set y [expr $y * $scalefactor]  
}
set x 5
set y 10
scale x y 2
puts "After scaling x=$x, y=$y"

Output:

After scaling x=10, y=20

The procedure "scale" shows how variables can be passed by reference so that the values of the variables can be modified and returned to the caller with changed values.

The requirement to be able to modify the values of variables is very common when writing Tcl scripts (and programmes in general). The mechanism for doing this in Tcl at first seems a little unusual but it is in fact quite simple.

The procedure must be called with the names of the variables to be modified rather than the values contained in those variables. Note that in the example the procedure "scale" is called with the arguments "x y 2" and not "$x $y 2".

The upvar command is then used to associate a variable in the procedure with the name of the variable that was used when the procedure was called. Assigning a new value to this variable causes the original variable that was used when the procedure was called to acquire the value in question.

The example also shows how the values of the variables passed to the "scale" procedure can be used by prefixing the variable name with the $ variable substitution operator.