Tek-Tips is the largest IT community on the Internet today!

Members share and learn making Tek-Tips Forums the best source of peer-reviewed technical information on the Internet!

  • Congratulations gkittelson on being selected by the Tek-Tips community for having the most helpful posts in the forums last week. Way to Go!

advantages/disadvantages of proc call

Status
Not open for further replies.

tomdagliusa

Programmer
May 31, 2000
34
US
Hi,

I prefer to write my procs so they accept a list on the call. This way, I can either key on certain attributes of the list to make decisions within the proc. This also has the added advantage of not requiring me to change any calls to the proc, as long as I make the changes backwards compatible. So instead of:

proc aProc {a b c} {
doSomething $a
if {$b == $someValue} {
.....
}
}

I have:
proc aProc {aList} {
if {[llength $aList] == $someSize} {
doThis [lindex $aList 2]

if {[lindex $aList 7] == $srcAddrDutIf1} {
doThat [lindex $aList 1] [lindex $aList 4]
}
}

Or, is it 6 of one, half dozen of the other?

Tom
 
It's certainly not a bad strategy. You just have to be careful to follow it consistently in your implementation. For example, consider the following procedure:

Code:
proc msg {argList} {
    puts [lindex $argList 0]
}

Now you have to remember that msg expects a list as an argument. So you'll get unexpected results if you accidentally try this:

[tt]% msg "Hello, world!"
Hello,[/tt]

Instead, you need to do this:

[tt]% [ignore]msg [list "Hello, world!"][/ignore]
Hello, world![/tt]

There are a couple of other strategies that you might want to consider, though. One is that you can define a procedure to accept optional arguments simply by providing default values to those arguments in your procedure definition. This can be a nice technique for extending existing procedures in a backwards compatible manner. Let's say that we had an existing version of msg defined like this:

[tt]proc msg {text} {
puts $text
}[/tt]

Now, we'd like to extend msg to accept a channel identifier argument, so we can send the message somewhere other than [tt]stdout[/tt]. To do so, we'll add a second argument to msg, but make it optional by providing a default value of "stdout":

[tt]proc msg {text {fid stdout}} {
puts $text
}[/tt]

You can now call msg with either 1 or 2 arguments:

[tt]msg "Hello, world!" ;# Send to stdout by default
msg "Hello, world!" stderr ;# Explictly send to stderr[/tt]

Another approach is that you can define a procedure so that it accepts a variable number of arguments. You do so by using the special argument name "args" in the procedure declaration. For example:

Code:
proc sum {args} {
    set total 0
    foreach val $args {
        set total [expr {$total + $val}]
    }
    return $total
}

This defines sum as a procedure that accepts 0 or more separate arguments. All of the arguments passed to sum are stored as a list in the variable args. If you provide no arguments to sum, then args contains an empty list. You can use all standard Tcl list manipulation commands on args.

You can also define a procedure so that it accepts a minimum number of arguments. Just provide explicit argument names for the required arguments, and then use args as the last argument. For example:

Code:
proc broadcast {msg args} {
    foreach channel $args {
        puts $channel $msg
    }
}

Now the first argument provided to broadcast is stored in msg, and any additional arguments are stored as a list in args:

[tt]% broadcast "Hello, world!" stdout stderr
Hello, world!
Hello, world![/tt]

- Ken Jones, President, ken@avia-training.com
Avia Training and Consulting, 866-TCL-HELP (866-825-4357) US Toll free
415-643-8692 Voice
415-643-8697 Fax
 
Hi Ken,

Thanks for the tips on using args. As a practice however, I prefer to make the var names somewhat intuitive. For instance, the variable name "ifTruePerformFullTest" is explicit enough, and especially so when viewed inline in the code. It may make the var names longer, but it cuts down on commenting. Given that, is there a way to do a C structure like entity in tcl? I'd love to be able to refer to indices within the call list as someChip.StatusRegister than as [lindex $aList $STATUS_REG], for instance.

Tom
 
There were some posts on this a while
ago at comp.lang.tcl, but for your purposes
an associative array would seem to
work as well.

Something like this possibly?
Code:
array set Chip {
StatusRegister 0
HeatThreshold 155
HandlerMethod ""
}
54 % parray Chip
Chip(HandlerMethod)  = 
Chip(HeatThreshold)  = 155
Chip(StatusRegister) = 0
 
Status
Not open for further replies.

Part and Inventory Search

Sponsor

Back
Top