views:

52

answers:

1
+1  Q: 

Weird TCL quirk

So I am very new and inexperienced to the ways of TCL programming. I wrote a script that calls a proc written by someone else, first removing the output file. It then does some additional logic I wrote.

I moved the logic into a second proc and instantly a bunch of it broke (namely the rm commands).

From what I can tell, the first program on a line inside the central execution (the text following proc definitions) executes normally without an "exec" command. However, if you move it inside a proc, it now needs an "exec" command.

Can anyone explain to me why TCL behaves this way?

e.g.

proc helloworld {} {
  puts "hi"
}
#works
rm my_file 
helloworld

..

proc helloworld {} {
  #doesn't work
  rm my_file 
  puts "hi"
}
helloworld

..

proc helloworld {} {
  #works
  eval rm my_file 
  puts "hi"
}
helloworld

..

proc helloworld {} {
  #works
  file delete my_file 
  puts "hi"
}
helloworld

*Note this weird behavior may be specific to the program I'm feeding the script to vmd, which has its own built in TCL behavior. Perhaps in your responses you can indicate if this is standard for other interpreters as well?

+3  A: 

An interactive tclsh session will try to exec an unknown command (such as rm). You cannot count on this behaviour in non-interactive script execution or, as you've discovered, in procs.

I can't see that this is documented in the tclsh man page, but the unknown man page does. See also the tclsh page on the Tcl wiki. In an interactive tclsh session, you can see what unknown does by typing:

info body unknown

[update]

Quoting from "Practical Programming in Tcl and Tk":

The unknown command provides a few other conveniences. These are used only when you typing commands directly. They are disabled once execution enters a procedure or if the Tcl shell is not being used interactively. The convenience features are automatic execution of programs, command history, and command abbreviation. These options are tried, in order, if a command implementation cannot be loaded from a script library.

glenn jackman
Interesting. That is surprising, considering that behavior seems like a bad idea. If I was writing tclsh/a tcl interpreter, I'd always require an `exec` statement for consistency. "Sometimes" allowing it seems like a recipe for disaster, especially considering that the diversity of scripting languages means that many people writing in language x aren't familiar with all its intricacies. Any TCL veterans out there that can defend why this approach is used?
Jason R. Mick
I presume these features were added to make an interactive Tcl session behave more like a unix shell. Tcl was written as a glue language, much like a unix shell is (easy execution of external commands). Perhaps Dr. Ousterhout or one of the early Tcl developers was a csh fan given how command history works (`!!`, `^old^new`, etc)
glenn jackman
I'm sure this falls into the category of "it seemed like a good idea at the time". It does make tclsh more shell-like to automatically run external commands if there's no procedure with that name. As to why it only works at the top-level, as glenn mentioned, there are a couple of other convenience features built into unknown, including command history, which you'd likely never be able to use reliably in a script.
Mark Bessey
@glenn: Tcl wasn't written as a glue language originally. It was written as a command language (meaning: a shell). Hence it's name: Tool Command Language (meaning: a shell for your tools, tool here refers to CAD programs or any other executable written in C). Ousterhout was actually quite surprised initially that people took his language and wrote large programs like the one that ran an offshore oil drilling platform.
slebetman