- Procs are global (visible from any call stack depth without need for declaration)
- Procs are a structure consisting of a list and a string
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 stringThat 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.JMN 2004-05-02 Good Grief TV, Yet another tendrilous interjection that looks suspiciously like an attempt to make your Bwise WalledGarden appear more integrated with the rest of the wiki...You've been mildly called to account by at least one other wikizen regarding relevance - and it's a testimony to the friendly nature of the Tcl community that relevance and coherence are not 'policed' as such. I much prefer the more or less self-moderated state of affairs we currently have on the wiki, and I don't claim to speak for others in this regard - but please Theo, keep the pet-project evangelism down a bit.I realize this particular page was last edited a while ago, but it's just one of a few examples of apparent Bwise name-dropping such as button, exec, introspection, idiom, label selection, Good Looking TkDon't feel I don't value your contributions to the wiki - I think the electrical-engineering perspective on Tcl is interesting; it's just that I don't feel your Bwise extension has as big a mindshare in Tcl as your extensive wiki-authoring might suggest. (I'd hazard a guess, in part due to your choice of license and meandering style of prose) Feel free to move/remove this commentary at some point TV(and/or wikignomes) - I just wanted to register a friendly protest.
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
MS notes that you can even make it a real executable that returns the saved data:
proc SillyPoem2 {} { return [join [lrange [split [info body SillyPoem2] \n] 2 end] \n] - Silly Poem Revisited - by R.Suchenwirth and M. Sofer written 2004-05-25 Hey Doc this is a real proc should you ever call it you'll get a shock... }You can also write a builder for such procs
proc buildDataProc {name str} { set basicBody [string map [list %NAME $name] { return [join [lrange [split [info body %NAME] \n] 2 end] \n] }] proc $name {} ${basicBody}$str }Note that the data string str cannot contain unmatched ", {, },[ or ]... and now I notice I'm being silly ...
proc buildDataProc {name str} { proc $name {} "return \"$str\"" }
I'd like to see procs actually become data structures. That is, invoking proc creates something akin to a dictionary with key/value pairs for body, arglist, name (optional if it's a lambda), documenation, user defined properties, etc. Widget properties are just additional properties associated with the command, giving you a basic object system. Add an upvar-like command that links command properties together and you've got megawidgets, inheritance and delagation. Rename would just modifiy the name property.And the possibilities for user-defined properties is cool too. Add documentation to a command. A command could carry around it's own unit tests. You could capture profiling or logging information as new properties. Every command would inherently be its own namespace.Plus then commands would have value semantics, and the command/value dichotomy would go away.
gold Here are procs from RS and MS loaded in a small program for the etcl console. Note that proc SillyPoem is 1) created, then 2) changed or overwritten in the program, as suggested above. We'll set a limit of 5 in a translator proc and return ? as an error warning. The phrase "trans SillyPoem {1}" resembles the chimera "array syntax on list".
# autoindent syntax and pretty print from ased editor. # written on Windows XP on eTCL # working under TCL version 8.5.6 and eTCL 1.0.1 # gold on TCL WIKI , 12may2011 package require Tk console show proc SillyPoem {author W.Shakespeare written 1567} {info body SillyPoem};#RS proc buildDataProc {name str} { proc $name {} "return \"$str\"" };#MS proc trans {nameb lister} { foreach item $lister { if { ( ! [ string is integer -strict $item ] ) || ( $item < 0 ) || ( $item >= 5 ) } { return ? } return [ lindex [ $nameb ] $item ] } buildDataProc book2 {boot fit good} buildDataProc SillyPoem {author W.Shakespeare written 1567} proc any_part_of_tcl_program {} { puts [ trans book2 {0} ] puts [ trans SillyPoem {1} ] puts [ trans book2 {7}] puts "[ trans book2 {0} ] [ trans book2 {1} ] [ trans SillyPoem {1}] [ trans book2 {2}] [ trans book2 {7}]" } any_part_of_tcl_program;#end etcl console output boot W.Shakespeare ? boot fit W.Shakespeare good ?Your linear string of if statements above can be replaced with this if you always pass in a list of integers:
if { $item >= 5 } { return ? } return [ lindex [ $nameb ] $item ]If you wanted to error check $item to verify it was an integer first, and in the range 0 .. 4, you could do it this way:
if { ( ! [ string is integer -strict $item ] ) || ( $item < 0 ) || ( $item >= 5 ) } { return ? } return [ lindex [ $nameb ] $item ]gold so changed, thanks.