Version 7 of Procs as data structures

Updated 2003-06-24 12:05:55

Richard Suchenwirth 2002-05-17 - In Streams I wrote: "Procs are data too, in some sense..." To clarify this, procs are data, with the following properties:

  • Procs are global (visible from any call stack depth without need for declaration)
  • Procs are a structure consisting of a list and a string

When a proc's name is evaluated in command position, the list elements are matched with the words following the name, to make a local stack frame, in which the string is then evaluated, and the result of that evaluation is returned to the caller.

But Tcl procs are more than C functions (where the compiler would complain at any breach of C syntax). Tcl procs are compiled (and similar problems may show up at that time) when first called. So what if a proc is never called? Philosophically, it seems to miss its destination, but then again, we can very well define and use a proc without ever calling it.

Imagine we want to build up a database of poems. Many ways are possible for doing this, including - with procs! Consider this code:

 proc SillyPoem {author R.Suchenwirth written 2002-05-17} {
    Hey Doc
    this isn't a real proc
    should you ever call it
    you'll get a shock...
 }

Perfectly legal Tcl, the interpreter doesn't complain. Calling SillyPoem of course leads to a number of error messages, ranging from

 no value given for parameter "author" to "SillyPoem"

to

 invalid command name "Hey"

But this poem wasn't intended to be called anyway. Rather, from any part of a Tcl program, you can access the two structure elements by

 info args SillyPoem ;# returns the list
 info body SillyPoem ;# returns the string

That the args are indeed a list is evident when you put additional spaces between words - info args will always join the args with exactly one space. On the other hand, info body returns the input string exactly, with spaces, newlines and all, so the body is a true string. The list might for instance be used for property-value pairs (like in the example), the string is, well, just a string, and we can store just about everything in it.

Changing a proc's "values" is just slightly more convolved, as all three arguments must be present in a call to proc, but you can get them from where they came:

 proc SillyPoem {author W.Shakespeare written 1567} [info body SillyPoem]
 proc SillyPoem [info args SillyPoem] {yes, just silly}

Again, this is a Tcl trivium for which I can imagine no practical use, but that's how philosophy goes - just thinking of something...

TV Don't forget the defaults for the arguments...

Bwise proc_window does this stuff reasonably well, thought I think it adds one newline too many to end of file. Native version insensitive tcl code, I think.


Afterthought: if you let the names of such "data procs" start with a # sign, you can be pretty sure that they won't be called by accident (except if escaped deliberately)..

 % proc # {} {puts hash}
 % # this is treated as a comment
 % \# ;# you'd have to escape the hash sign to call it:
 hash

Procs as objects - Arts and crafts of Tcl-Tk programming