The following is a brief tutorial on the tcl language that I whipped up. 
For the purposes of example, all lines beginning with "%" indicate things
you can type at the shell prompt. You should start the "wish" shell
program at this time to type in the examples. If you don't know what that
is, read the README that comes with your tcl/tk distribution. 


Lesson 1

There are only four basic things you need to remember to program tcl.


#1: The language is 100% internally consistent. All commands, without
    exception, take the same form. That form is:

  procname ?argument? ?argument? ?argument? ...

where "procname" is the name of the function and ?argument? is a series of
arguments to pass to the function. Here is an example of the "set"
command: 

  % set a 15
  15  <---- this is the return value of the "set" function.

This sets the variable "a" to the value of 15 and returns that value as
as output. It takes the form: 

  set varname ?value?

The "expr" command evaluates a mathematical expression. It takes an
arbitrary number of values. 

  % expr 4 + 5 + 2
  11  <---- return value (in the future I will not put the "<--" arrows).


#2: To evaluate a command (procedure) and return that value "inline", use
    brackets "[]" 


  % set a [expr 5 + 7]
  12

"a" now has a value of 12.


#3: To evaluate a variable, prepend the name with a "$"

The "puts" command prints a string to the console. It stands for "put
string" 

  % puts "hello world"
  hello world

  % set a [expr 11 + 12]
  23

  % puts "The value of a is $a"
  The value of a is 23

The main form of "puts" only takes one argument. The quotes ("") are used
to contain the string. Otherwise the spaces would separate the words and
they would be considered separate arguments.


#4: To prevent variables or special characters from being evaluated,
    enclose them in {}.  This seems simple at first, but it can get very
    complex when you nest them in "lists".  I'll get into this later. 

  % set a hello
  hello

  % set b "$a world"
  hello world

  % set c {$a world}
  $a world

  % set d {"a string with quotes"}
  "a string with quotes"


That all of the basics. From here it's just learning the built in
commands. The command to define a new function is "proc". It takes the
form:

  proc name args body

  an example:

  proc add {x y} {
        return [expr $x + $y]
  }

  now you can call the command:

  % add 4 5
  9


Notice that the functions argements are enclosed in {} and the functions
body is also enclosed in {}. This prevents them from being evaluated. If
the procedure only took one argument, it would be legal to not enclose it 
since 'message' and '{message}' are both lists of length one: 

  proc print message {puts $message}


Notice two things. 1) The commands in the language are all in the form
mentioned in rule #1. 2) The {} can enclose newlines (return characters)
that that is the most common form for the function body. 

Now for a little more complex stuff. In tcl, all variables are stored as
either strings or lists. The examples above all use strings. A list is a
special form of string where the the list items are separated by spaces. 

 % set list {abc cde efg hij}
 abc def ghi jkl


There are several commands for dealing list lists:

 llength  - returns the length if a list
 lindex   - returns the item if a list at a given index
 lrange   - returns a range of items from a list as a list


  % llength $list
  4

  $lindex $list 2
  ghi


Notice that it returned the third element of the list. This is because
lists are 0 index based which means the first item is 0 and the last is
"length - 1". 


  % lrange $a 2 3
  ghi jkl

  % lrange $a 1 end
  def ghi jkl

"end" is a special index value that evaluates as the last item in the list.

 
  % set a [lrange $a 1 end]
  def ghi jkl

  % llength $a
  3

I think you get the picture. Now, what If you want to have a list item
that contains spaces? 

  % set list {"a single item" another few items}
  "a single item" another few items

  % llength $list
  4

  % lindex $list 0
  a single item

  % lindex $list 1
  another

Enough of that. There are several other variations. In a lot of cases, ""
and {} can be used interchangeably. One last thing: 

  % set list {{a single item} another few items}
  {a single item} another few items

  % lindex $list 0
  a single item

But it is not possible to nest quotes (""). This is the distinguishing
factor for brackets ({}).

The outer encasing of a string with spaces is always stripped upon
evaluation. That might be a candidate for rule #5. 


Lesson 2

The next section deals with graphics. You will want to spend a lot of time
playing with graphics under tcl/tk to get a feel for the power. You do
simple things quickly and very complex things with little practice. 

Graphic objects are called "widgets". These are things like windows
(called toplevels), buttons, text fields and radio buttons. widgets live
in a tree with a single root node very similar to a binary tree. The root
of the tree is named "." since it doesn't have a name.  Children widgets
of "." might be called ".button1" and ".frame1". If they also had children
the tree would look like this: 

 .
 .button1
 .frame1
 .frame1.button2
 .frame1.button3

When Tcl/Tk is started, it automatically creates the root node "." in the
widget tree and this widget is a toplevel window (a window with a title
bar). It looks like this (well, almost). 

+-----------+
|window     |  <-- I'll use this crude approximation, but you get the idea
+-----------+ 
|           |
|           |
|           |
|           |
+-----------+

There are several special commands for creating graphical widgets and I
won't list them all but these are a few: 

  toplevel - creates a new window like "."
  frame    - creates a container frame to hold other children
  button   - creates a push button with text
  label    - creates a label with text
  entry    - creates a single line text input field
  text     - creates a multi-line text input field


With one exception, when a widget is created, it is not immediately
displayed. You must use one of three "geometry managers" to place the
widget in the space available. The single exception to this is a
"toplevel" window. When it is created, the window displays immediately. 

Let's create a button:

  % button .b1 -text "hello world"
  .b1

Now we have a button named ".b1" that displays the text "hello world"
(without the quotes).  This is useless until we place it in the window. As
I mentioned, there are several ways of doing this, but for the purposes of
the initial exercise, I will stick to one: the "packer". 

The "packer" allows you to "pack" widgets into the space remaining in the
window. Examples will make all of this concrete. Let's pack this button.
First, use the mouse to resize the root window a little. Otherwise, the
first "pack" will resize the window to fit the button and we don't want
that just yet. I'll explain later (if I remember). 

  % pack .b1 -side top

This returns the name of the created widget and now we have on the screen: 


+-------------------+
|window             |
+-------------------+
|  +-------------+  |
|  | hello world |  |
|  +-------------+  |
|                   |
|                   |
|                   |
+-------------------+

Notice how the button is sitting at the top of the window. This is what
the "-side" option does. The remaining space left to the packer is
anything below the button. Let's create another one and pack it too. 

  % button .b2 -text "me, too"
  .b2
  % pack .b2 -side top -fill x

+-------------------+
|window             |
+-------------------+
|  +-------------+  |
|  | hello world |  |
|  +-------------+  |
|+-----------------+|
||     me, too     ||
|+-----------------+|
|                   |
|                   |
+-------------------+

Notice how the second button fills the width of the window. This is what
the "-fill" option does. The options you can use with it are "x", "y",
"both" or "none". Let's repack that second button with different options. 


  % pack .b2 -side bottom -fill none

+-------------------+
|window             |
+-------------------+
|  +-------------+  |
|  | hello world |  |
|  +-------------+  |
|                   |
|                   |
|    +---------+    |
|    | me, too |    |
|    +---------+    |
+-------------------+

  % pack .b2 -side top -expand 1

+-------------------+
|window             |
+-------------------+
|  +-------------+  |
|  | hello world |  |
|  +-------------+  |
|                   |
|                   |
|    +---------+    |
|    | me, too |    |
|    +---------+    |
|                   |
|                   |
+-------------------+

The second button is now filling all the space not taken by the first
button. This is what the "-expand" option does. Let's try expand and fill
together: 

  % pack .b2 -side top -expand 1 -fill both

+-------------------+
|window             |
+-------------------+
|  +-------------+  |
|  | hello world |  |
|  +-------------+  |
|+-----------------+|
||                 ||
||                 ||
||     me, too     ||
||                 ||
||                 ||
|+-----------------+|
+-------------------+

Hrm... This is starting to make sense.