proc demo {first {second "none"} args} {
puts "first = $first"
puts "second = $second"
puts "args = $args"
}
demo one
demo one two
demo one two three four fiveresults in:first = one second = none args = first = one second = two args = first = one second = two args = three four five
example args (using XOTcl)
Class Club -parameter {id {name unknown}}
Class Player -superclass Club -parameter {{name unknown} {position unknown}}
Player proc show_players args {
if { [string length $args] == 0} {
puts "Show players DB"
foreach p [my info instances] {
puts "[$p name] [$p position]"
}
return
}
set pos [string toupper $args]
puts "Players with postition $pos:"
foreach p [my info instances] {
foreach char [split $pos {}] {
if {[string first $char [$p position]] == 1} {
puts "[$p name] [$p position]"
break
}
}
}
}Is it just me, or is that a pretty poor example of args? You do [string length $args] and [string toupper $args] but you firmly established that args is a list, not a string. It is generally accepted as bad practice to perform string operations on lists.LES But, if everything is a string, aren't lists strings too? On the other hand, there has been quite some debate on whether everything is a list rather than a string...LV I don't know that I would go so far as saying that it is bad practice to perform string operations on lists.I would say that it is generally bad practice to perform list operations on variables known only to have strings. And I would say that some string operations on lists may result in results that , at first blush, one might not expect.Lars H: The problem with applying string operations on known pure lists like $args is basically shimmering. Applying a string operation will require generation of a string representation, and the cost for that (in memory and processing time) is often better avoided whenever possible. If you pass multi-megabyte lists around (something Tcl 8 handles beautifully well), you probably don't want to double the memory footprint by also generating their string representations.An extreme example:
set val x
for {set n 1} {$n<=64} {incr n} {set val [list $val $val]}
puts "Tcl will get this far."; flush stdout
string length $val
puts "But it runs out of memory before it gets this far.!"LV So then the example isn't a poor example of args - but a poor example of good performance.MG offers a quick example off the top of his head (and therefore untested), on his way through...
proc randomCmd {args} {
set error {wrong # args: should be "randomCmd ?-arg value ...? string"}
set num [llength $args]
if { $num == "0" || ($num%2) == 0 } {
error $error;
}
array set opts [list -width 5 -height 5 -fg [list] -bg [list] -foreground blue -background red]
if { $num > 1 } {
foreach {x y} [lrange $args 0 end-1] {
if { ![info exists opts($x)] } {
error "unknown option \"$x\"";
}
set opts($x) $y
}
}
foreach {x y} [list -fg -foreground -bg -background] {
if { [llength $opts($x)] > 0 } {
set opts($y) $opts($x)
}
unset opts($x)
}
echo "String is \"[lindex $args end]\". Apply these options: [array get opts]"
}LV Here's where I am trying to use args - maybe someone has a suggestion. My code is this:
% proc d {name args} {
puts "DEBUG: $name: $args"
}
% d mainline "this is the first spot in the mainline"
DEBUG: mainline: {this is the first spot in the mainline}That is to say, it is intended as a place to control debug statements. I can just return rather than do the puts, to turn off the debugging.HOWEVER, the debugging output looks peculiar. Not a problem - it is just for debugging. But if I were going to use this for something else, I wouldn't want the extra {} in there.RS: try join $args to get rid of braces :)See also magic names.
