tags:

views:

117

answers:

2

I am writing a proc to create a header in an output file.

Currently it needs to take an optional parameter, which is a possible comment for the header.

I have ended up coding this as a single optional parameter

proc dump_header { test description {comment = ""}}

but would like to know how I can achieve the same using args

proc dump_header { test description args }

It's quite easy to check for args being a single blank parameter ($args == ""), but doesn't cope well if passing multiple parameters - and I need the negative check anyway.

A: 

I use tcllib's cmdline library to do option parsing.

This is the example from cmdline documentation:

set options {
    {a          "set the atime only"}
    {m          "set the mtime only"}
    {c          "do not create non-existent files"}
    {r.arg  ""  "use time from ref_file"}
    {t.arg  -1  "use specified time"}
}
set usage ": MyCommandName \[options] filename ...\noptions:"
array set params [::cmdline::getoptions argv $options $usage]

if {  $params(a) } { set set_atime "true" }
set has_t [expr {$params(t) != -1}]
set has_r [expr {[string length $params(r)] > 0}]
if {$has_t && $has_r} {
    return -code error "Cannot specify both -r and -t"
} elseif {$has_t} {
    ...
}

So, in your case, you'd just use args in place of argv in the above example.

Trey Jackson
+4  A: 

Your proc definition is incorrect (you'd get the error message too many fields in argument specifier "comment = """). Should be:

proc dump_header { test description {comment ""}} {
    puts $comment
}

If you want to use args, you could examine the llength of it:

proc dump_header {test desc args} {
    switch -exact [llength $args] {
        0 {puts "no comment"}
        1 {puts "the comment is: $args"}
        default {
            puts "the comment is: [lindex $args 0]"
            puts "the other args are: [lrange $args 1 end]"
        }
    }
}

You might also want to pass name-value pairs in a list:

proc dump_header {test desc options} {
    # following will error if $options is an odd-length list
    array set opts $options

    if {[info exists opts(comment)]} {
        puts "the comment is: $opts(comment)"
    }
    puts "here are all the options given:"
    parray opts
}
dump_header "test" "description" {comment "a comment" arg1 foo arg2 bar}

Some prefer a combination of args and name-value pairs (a la Tk)

proc dump_header {test desc args} {
    # following will error if $args is an odd-length list
    array set opts $args
    if {[info exists opts(-comment)]} {
        puts "the comment is: $opts(-comment)"
    }
    parray opts
}
dump_header "test" "description" -comment "a comment" -arg1 foo -arg2 bar
glenn jackman
Thanks.For other cases I think I would prefer the name-value pairs... but in this case I guess your answer translates "to handle all cases you have to treat as an array". Which is fine.
itj