1
votes

Is there a way to pass arguments of a proc from command line? I have my proc in a script. I would like to give its arguments from command line. Is there any equivalent command like "$@" in shell scripting?

3

3 Answers

4
votes

You can get command line arguments using these predefined variables.

$argc - number items of arguments passed to a script.
$argv - list of the arguments.
$argv0 - name of the script.
4
votes

There are many parts of command line arguments:

  • $argv — a Tcl list of “useful” argument words. Excludes the name of the script.
  • $argc — the number of “useful” argument words (i.e., the length of $argv); very rarely used given that [llength $argv] works just as well.
  • $argv0 — The name of main script being executed.
  • [info nameofexecutable] — The program that is executing the script. Often called tclsh or wish (or some variation on that with version numbers and an extension) but definitely not necessarily so.

The simplest way of passing all “useful” argument words — all the words that you'd normally think of as being arguments — to a procedure is to do this (assuming Tcl 8.5 or later):

theProc {*}$argv

Note that this must come after all calls to proc are done; proc is a command that defines a procedure, not a declaration of a procedure. (The difference? Declarations could conceivably be seen further up the file, but Tcl doesn't work like that.)

I often like to wrap the above in a bit of exception handling in production code so that any errors can be reported nicely instead of dumping a stack trace:

if {[catch {theProc {*}$argv} msg]} {
    handleError $msg
}

Prior to 8.5, you needed a more ugly way:

eval theProc $argv

This is still safe (in a formal sense) because of how Tcl guarantees to construct list values, and the fact that we know $argv to be a proper list.

0
votes

There is also args for variable number of arguments.

proc foo args {
    foreach arg $args {
        puts "arg=$arg"
    }
}

so calling foo will print this:

% foo 1
arg=1
% foo 1 2 3
arg=1
arg=2
arg=3
% 

Please note that calling this proc with $argv will treat entire content of $argv as a single element in $argc list:

$ cat ar.tcl
#!/usr/bin/tclsh
proc foo args {
    foreach arg $args {
        puts "arg=$arg"
    }
}

foo $argv
$ 
$ ./ar.tcl 1 2 3
arg=1 2 3

you will need to use [lindex $args 0] to get the real $argv