Version 1 of subproc

Updated 2006-03-17 02:56:43

by slebetman:

Procs with subcommands are very common in Tcl and Tk. A good example is the string command which rolls all string operations into a single proc. I personally like this style of programming (though it may be verbose at times) so I've written the following helper proc to construct such procs-with-subcommands:

    proc subproc {name procs} {
      set body "set op \[lindex \$args 0\]\n"
      append body "set args \[lrange \$args 1 end\]\n"
      append body "switch -exact \$op \{\n"
      foreach {op params script} $procs {
        if {$op != "default"} {
          append body "{$op} \{\n"
        } else {
          append body "default \{\n"
        }
        for {set i 0} {$i < [llength $params]} {incr i} {
          set par [lindex $params $i]
          if {$par == "args"} {
            append body "set {$par} \[lrange \$args $i end\]\n"
          } else {
            append body "set {$par} \[lindex \$args $i\]\n"
          }
        }
        append body "$script\}\n"
      }
      append body "\}\n"
      proc $name {args} $body
    }

Defining a subproc is easy and defining the body of subcommands work just like writing a regular proc:

    subproc listOp {

      index {L idx} {
        return [lindex $L $idx]
      }

      dump {L} {
        foreach x $L {
          if {[listOp length $x] == 1} {
            puts $x
          } else {
            foreach y $x {
              if {[listOp length $y] == 1} {
                puts "  $y"
              } else {
                foreach z $y {
                  puts "    $z"
                }
              }
            }
          }
        }
      }

      range {L start end} {
        return [lrange $L $start $end]
      }

      length {L} {
        return [llength $L]
      }
    }

Now you can use the proc listOp:

    % set test [list This is "very cool"]
    This is {very cool}
    % listOp length $test
    3
    % listOp dump $test
    This
    is
      very
      cool