'''Tcl for Beginners''', originally by [slebetman], rewritten by others, is another [Learning Tcl%|%introduction] to [Tcl] ** See Also ** [Dodekalogue]: [[`[foreach]`]: A simple and powerful command that is used extremely often [gotcha]: [Why can I not place unmatched braces in Tcl comments]: ** It's All about Commands ** The best way to approach Tcl is to think of the command line, be it [MS-DOS%|%DOS] or [bash] or tcsh or Cisco's telnet shell. Just like in DOS, the first word of a Tcl statement is always a command. All statements in Tcl work just like running a program from the command line. That is, the first word is a ''command'' and the following words are ''parameters'' to that command. For example, in DOS to list the contents of a directory you would type: ======none dir c:\path\to\folder ====== in Tcl you would write: ====== glob /path/to/folder/* ====== Just like in DOS, the first word of a Tcl statement is always a command. [[`[glob]`] is one of the [Tcl Commands%|%commands] available in Tcl. Another useful command is [[`[puts]`], which, like the ''echo'' command in DOS, prints things out on the screen: ====== puts Hello ====== One mnemonic device is '''put''' '''s'''tring. In the command above, there are no quotes around `Hello`. No quotes are needed in Tcl because words are already just that: '''words'''. In Tcl, everything [everything is a string%|%is just a word]. Of course there are commands that interpret words as numbers so that we can get some math done, but it's up to each individual command to decide how it wants to treat any particular word. Tcl makes no distinction. [[`[set]`] only takes two arguments. The following code will therefore fail: ====== set foo this is not kosher ====== will result in ======none error: wrong # args: should be "set varName ?newValue?" ====== But what if we want to assign several words to `foo`? One answer it to use braces... ** Using Braces ** Since everything is a word in Tcl, and words are separated by white space, one question that soon arises is how to get spaces into words if we need them there. If, for example, we want [[`[puts]`], to print an entire sentence to the screen, white space and all, we can do it with braces: ====== puts {Hello World!} ====== With the braces in place, Tcl now sees the entire sentence as a single word. Thus we see that in contrast to what it means to humans, in Tcl, "word" is a string which may contain white space. Braces only have this special meaning when they are at the beginning of a word. In the middle of a word, they're just brraces. Not even newlines can stop braces: ====== puts {This is a whole paragraph inside braces. Braces just don't quit until the matching closing brace is found. Backslashed \} braces don't close it Off. Neither do "Quotes". {other matching braces} are OK, too. But finally, we get to the closing brace. } ====== ** Using Variables ** Use [[`[set]`] to set the value of a variable: ====== set greeting Hello ====== To get the value back out of a variable use a dollar sign. For example, to print `Hello`: ====== puts $greeting ====== This works even if there is white space in the greeting: ====== set greeting {Hello There} puts $greeting ====== That's because Tcl substitutes the entire value of the variable into the the spot where `$greeting` was. ** Command Substitution ** Variable substitution isn't the only substitution game in town. There's also command substitution. This is done with square brackets. To print `Hello` to the screen using command substitution: ====== set greeting Hello puts [set greeting] ====== Notice that when it only gets one argument instead of two [[`[set]`] returns with the value of the variable instead of setting it. Notice also that we just used the name of the variable without prepending a dollar sign to it. If we had prepended the dollar sign, it would have been equivalent to typing `set Hello`, in which case [[`[set]`] would have gone to find the value of the variable named, "Hello", failed to find it, and returned an error. Knowing that, you should be able to make sense of the following code: ====== Set Hello Howdy set greeting Hello puts [set $greeting] ====== What will be printed to the screen? That's right: ======none Howdy ====== '''Extra Credit''' (not really a beginner thing): ====== puts [expr $$greeting] ====== What will be printed? Yes, once again, it's ======none Howdy ====== Why? Hint, what does `[[puts $$]` do? ** Commenting Code ** Sometimes, particularly when we think we're doing something really clever, we want to add comments to our code so that other humans can make more sense of it. To do this in Tcl, we use the pound character, but only at the beginning of a command: ====== #puts {This line won't ever happen, because it's commented} puts Whew! ====== ** Using Double Quotes ** Braces inhibit variable substitution, command substitution, and most backslash substitution: ====== set name John #warning - This next line won't substitute in John. It just prints exactly #what is in the braces, including the $. puts {Hello $name} ====== When we want those substitutions, but we also need white space to just be white space, we can use double quotes instead of braces. Double quotes have the same purpose as braces, but also allow all substitutions: ====== set name John set greeting "Hello, $name! Hello again, [set name]!" ====== As with braces, newlines inside quotes are just newlines: ====== puts "In double quotes, newlines are just newlines. If you escape a newline, \ it disappears entirely. Braces are just {braces}, and other \"double quotes\" can be escaped. [ set value {Command Substitution , which should really be called "script substitution"} set value ], is also not a problem at all. Notice that there were multiple commands in that last command subsitution, and the value of the last command is what actually takes the place of the entire command substitusion. It doesn't hurt to escape \{braces\}, but it isn't necessary, either. Escaping regular \letters doen't do anything at all to them. An \a is just an a. Finally, we get to the closing quote." " ====== ** Using Backslashes ** In addition to variable and command substitution, there is on other substituion device: Backslashes. They are used in Tcl in a manner very similar to that of [C]/[C++]. The following are backslash substitutions understood by Tcl: '''`\a`''': Audible alert (bell) (0x7) '''`\b`''': Backspace (0x8) '''`\f`''': Form feed (0xc) '''`\n`''': Newline, LF (0xa) '''`\r`''': Carriage-return, CR (0xd) '''`\t`''': Tab (0x9) '''`\v`''': Vertical tab (0xb) The additional backslash sequences, '''`\x`''' and '''`\u`''', are some documented in the [Dodekalogue]. They point to the fact that Tcl is not restricted to 8-bit characters, a limitation of some other languages. If a `\` is followed by up to 3 digits of numbers, than it is treated as an octal value for a character and the actual character is then substituted in its place. Any other character following a `\` is replace with itself. This is an 'escape' mechanism that enables you to make character just be themselves in places where Tcl would normally assign some special meaning to them: ====== puts "what do we mean when we say, \"word\"?" ====== If a backslash '''\''' appears at the end of a line, then that line continues on to the next line: ====== puts \ "Continued from the line above" ====== This is to allow a long line of code to be split into multiple lines if you run out of space in your text editor. ** What is a list? ** about [list%|%lists], except that some command might interpret words passed to them as various things, including possibly lists. It does specify, however, that a about lists, except that some command might interpret words passed to them as be strings. Commands, in turn, are composed of words. This strongly implies script is a string, can be broken down into commands, which therefore must also built-in `[list]` commands of Tcl accept a word as a list if and only that the syntax of a command must be adequate to express a list. There are built-in [[`[list]`] commands of Tcl will accept a word as a list if and only if the word would be conforms could be parsed just as a command is parsed. In ====== set a "A B C" lindex $a 0 ====== The above commands return : ======none A B C A ====== However, not every string that can be interpreted as a command is a list. [[`[lindex]`] returns the list element, located at the given index. Indices start at 0. set command {list {*}{one two three}} lindex $command 0 ;# -> error: list element in braces followed by "{one" instead of space ====== result: ====== B ====== It's possible for a list to contain another list: ====== set a "A {B C} D" lindex $a 1 ====== result: ======none A {B C} D B C ====== Remember that not all strings are lists. Remember that not all strings are lists. that doesn't mean that any value given to `[split]` is a well-formed Although [[`[split]`] can be used to convert any string into a list of words, that doesn't doesn't mean that any value given to [[`[split]`] is a well-formed ** DO ** ** Conditional Constructs ** The few rules that have just been described constitute the entirety of the Tcl language. Really! That's it. There's nothing more. There doesn't need to be anything more because believe it or not, those rules are entirely sufficient to create everything else that's needed in a fully-featured language. Witness [[`[if]`] a necessary construct in any language, which in Tcl can be implemented as just another command. It takes a word that serves as the condition, and another word that serves as the script to run in the event that the criteria is true: ====== if {1} { puts "1 is always true!" } ====== Notice that we braced the 1 even though it wasn't strictly necessary. Why? To advocate [Brace your expr-essions%|%good programming habits. Until you learn enought to know exactly when not to, you should '''always''' [Brace your expr-essions%|%brace your expressions]. Here's another example: ====== if {0} { Anything at all can go here, even syntactically-invalid\{ stuff, because Tcl will not attempt to evaluate this word, as the condition is false. } ====== * Do write lots of comments in your code about what your code does, what you tried that didn't work (and why, if known). * Do study the documentation and others' code to understand 'upvar', 'uplevel'. * Learn how to use `[exec]` so that you can start using Tcl to drive external programs * Learn how to use [[`[exec]`] so that you can start using Tcl to drive drive external programs ** DON'T ** * Don't have unescaped unmatched brackets ANYWHERE, including comments. Use a text editor that helps you by showing bracket matching. ** Getting Stuff Done ** * [tcllib] is full of useful code. Try to use it as much as possible, a wide use of [tcllib] really saves time, and it is frequently updated. * If you need speed, be aware that Tcl can be extended easily (using [C],[C++]...). Avoid writing your own extensions if existing ones can do the job. * Do split your code into different [namespace]s (and files) when it overcomes ca. a thousand lines. <> Tutorial ** Regarding Variables and Values example ** ====== set foo "this is cool" set bar foo puts [set $bar] puts [set [set bar]] ======