text:
Tcl Programming/Debugging

Tcl itself is quite a good teacher. Don't be afraid to do something wrong - it will most often deliver a helpful error message. When tclsh is called with no arguments, it starts in an interactive mode and displays a "%" prompt. The user types something in and sees what comes out: either the result or an error message.

Trying isolated test cases interactively, and pasting the command into the editor when satisfied, can greatly reduce debugging time (there is no need to restart the application after every little change - just make sure it's the right one, before restarting.)

A quick tour
Here's a commented session transcript:

% hello invalid command name "hello" OK, so we're supposed to type in a command. Although it doesn't look so, here's one: % hi     1  hello 2 hi Interactive tclsh tries to guess what we mean, and "hi" is the unambiguous prefix of the "history" command, whose results we see here. Another command worth remembering is "info": % info wrong # args: should be "info option ?arg arg ...?" The error message tells us there should be at least one option, and optionally more arguments. % info option bad option "option": must be args, body, cmdcount, commands, complete, default, exists, functions, globals, hostname, level, library, loaded, locals, nameofexecutable, patchlevel, procs, script, sharedlibextension, tclversion, or vars Another helpful error: "option" is not an option, but the valid ones are listed. To get information about commands, it makes sense to type the following: % info commands tell socket subst lremove open eof tkcon_tcl_gets pwd glob list exec pid echo dir auto_load_index time unknown eval lrange tcl_unknown fblocked lsearch gets auto_import case lappend proc break dump variable llength tkcon auto_execok return pkg_mkIndex linsert error bgerror catch clock info split thread_load loadvfs array if idebug fconfigure concat join lreplace source fcopy global switch which auto_qualify update tclPkgUnknown close clear cd for auto_load file append format tkcon_puts alias what read package set unalias pkg_compareExtension binary namespace scan edit trace seek while flush after more vwait uplevel continue foreach lset rename tkcon_gets fileevent regexp tkcon_tcl_puts observe_var tclPkgSetup upvar unset encoding expr load regsub history exit interp puts incr lindex lsort tclLog observe ls less string Oh my, quite many... How many? % llength [info commands] 115 Now for a more practical task - let's let Tcl compute the value of Pi. % expr acos(-1) 3.14159265359 Hm.. can we have that with more precision? % set tcl_precision 17 17 % expr acos(-1) 3.1415926535897931 Back to the first try, where "hello" was an invalid command. Let's just create a valid one: % proc hello {} {puts Hi!} Silently acknowledged. Now testing: % hello Hi!

Errors are exceptions
What in Tcl is called error is in fact more like an exception in other languages - you can deliberately raise an error, and also catch errors. Examples:

if {$username eq ""} {error "please specify a user name"}

if [catch {open $filename w} fp] { error "$filename is not writable" } One reason for errors can be an undefined command name. One can use this playfully, together with catch, as in the following example of a multi-loop break, that terminates the two nested loops when a matrix element is empty: if [catch { foreach row $matrix { foreach col $row { if {$col eq ""} throw }   } }] {puts "empty matrix element found"} The throw command does not exist in normal Tcl, so it throws an error, which is caught by the catch around the outer loop.

The errorInfo variable
This global variable provided by Tcl contains the last error message and the traceback of the last error. Silly example:

% proc foo {} {bar x} % proc bar {input} {grill$input} % foo invalid command name "grillx"

% set errorInfo invalid command name "grillx" while executing "grill$input" (procedure "bar" line 1) invoked from within "bar x"   (procedure "foo" line 1) invoked from within "foo"

If no error has occurred yet, errorInfo will contain the empty string.

The errorCode variable
In addition, there is the errorCode variable that returns a list of up to three elements:
 * category (POSIX, ARITH, ...)
 * abbreviated code for the last error
 * human-readable error text

Examples: % open not_existing couldn't open "not_existing": no such file or directory % set errorCode POSIX ENOENT {no such file or directory}

% expr 1/0 divide by zero % set errorCode ARITH DIVZERO {divide by zero}

% foo invalid command name "foo" % set errorCode NONE

Tracing procedure calls
For a quick overview how some procedures are called, and when, and what do they return, and when, the trace execution is a valuable tool. Let's take the following factorial function as example: proc fac x {expr {$x<2? 1 : $x * [fac [incr x -1]]}} We need to supply a handler that will be called with different numbers of arguments (two on enter, four on leave). Here's a very simple one: proc tracer args {puts $args} Now we instruct the interpreter to trace enter and leave of fac: trace add execution fac {enter leave} tracer Let's test it with the factorial of 7: fac 7 which gives, on stdout: {fac 7} enter {fac 6} enter {fac 5} enter {fac 4} enter {fac 3} enter {fac 2} enter {fac 1} enter {fac 1} 0 1 leave {fac 2} 0 2 leave {fac 3} 0 6 leave {fac 4} 0 24 leave {fac 5} 0 120 leave {fac 6} 0 720 leave {fac 7} 0 5040 leave So we can see how recursion goes down to 1, then returns in backward order, stepwise building up the final result. The 0 that comes as second word in "leave" lines is the return status, 0 being TCL_OK.

Stepping through a procedure
To find out how exactly a proc works (and what goes wrong where), you can also register commands to be called before and after a command inside a procedure is called (going down transitively to all called procs). You can use the following step and interact procedures for this:

proc step {name {yesno 1}} { set mode [expr {$yesno? "add" : "remove"}] trace $mode execution $name {enterstep leavestep} interact }

proc interact args { if {[lindex $args end] eq "leavestep"} { puts ==>[lindex $args 2] return }   puts -nonewline "$args --" while 1 { puts -nonewline "> " flush stdout gets stdin cmd if {$cmd eq "c" || $cmd eq ""} break catch {uplevel 1 $cmd} res if {[string length $res]} {puts $res} } }

proc sreverse str { set res "" for {set i [string length $str]} {$i > 0} {} { append res [string index $str [incr i -1]] }   set res }
 * 1) Test case, a simple string reverter:

step sreverse sreverse hello
 * 1) -- Turn on stepping for sreverse:

step sreverse 0 puts [sreverse Goodbye]
 * 1) -- Turn off stepping (you can also type this command from inside interact):

The above code gives the following transcript when sourced into a tclsh:

{set res {}} enterstep --> ==> {for {set i [string length $str]} {$i > 0} {} { append res [string index $str [incr i -1]] }} enterstep --> {string length hello} enterstep --> ==>5 {set i 5} enterstep --> ==>5 {incr i -1} enterstep --> ==>4 {string index hello 4} enterstep --> ==>o {append res o} enterstep --> ==>o {incr i -1} enterstep --> ==>3 {string index hello 3} enterstep --> ==>l {append res l} enterstep --> ==>ol {incr i -1} enterstep --> ==>2 {string index hello 2} enterstep --> ==>l {append res l} enterstep --> ==>oll {incr i -1} enterstep --> ==>1 {string index hello 1} enterstep --> ==>e {append res e} enterstep --> ==>olle {incr i -1} enterstep --> ==>0 {string index hello 0} enterstep --> ==>h {append res h} enterstep --> ==>olleh ==> {set res} enterstep --> ==>olleh eybdooG

Debugging
The simplest way to inspect why something goes wrong is inserting a puts command before the place where it happens. Say if you want to see the values of variables x and y, just insert puts x:$x,y:$y (if the string argument contains no spaces, it needs not be quoted). The output will go to stdout - the console from where you started the script. On Windows or Mac, you might need to add the command console show to get the substitute console Tcl creates for you, when no real one is present.

If at some time you want to see details of what your program does, and at others not, you can define and redefine a dputs command that either calls puts or does nothing: proc d+ {} {proc dputs args {puts $args}} proc d- {} {proc dputs args {}} d+ ;# initially, tracing on... turn off with d-

For more debugging comfort, add the proc interact from above to your code, and put a call to interact before the place where the error happens. Some useful things to do at such a debugging prompt: info level 0   ;# shows how the current proc was called info level     ;# shows how deep you are in the call stack uplevel 1 ...  ;# execute the ... command one level up, i.e. in the caller of the current proc set ::errorInfo ;# display the last error message in detail

Assertions
Checking data for certain conditions is a frequent operation in coding. Absolutely intolerable conditions can just throw an error:

if {$temperature > 100} {error "ouch... too hot!"}

Where the error occurred is evident from ::errorInfo, which will look a bit clearer (no mention of the error command) if you code

if {$temperature > 100} {return -code error "ouch... too hot!"}

If you don't need hand-crafted error messages, you can factor such checks out to an assert command:

proc assert condition { set s "{$condition}" if {![uplevel 1 expr $s]} { return -code error "assertion failed: $condition" } } Use cases look like this:

assert {$temperature <= 100}

Note that the condition is reverted - as "assert" means roughly "take for granted", the positive case is specified, and the error is raised if it is not satisfied.

Tests for internal conditions (that do not depend on external data) can be used during development, and when the coder is sure they are bullet-proof to always succeed, (s)he can turn them off centrally in one place by defining

proc assert args {}

This way, assertions are compiled to no bytecode at all, and can remain in the source code as a kind of documentation.

If assertions are tested, it only happens at the position where they stand in the code. Using a trace, it is also possible to specify a condition once, and have it tested whenever a variable's value changes:

proc assertt {varName condition} { uplevel 1 [list trace var $varName w "assert $condition ;#"] } The ";#" at the end of the trace causes the additional arguments name element op, that are appended to the command prefix when a trace fires, to be ignored as a comment.

Testing:

% assertt list {[llength $list]<10} % set list {1 2 3 4 5 6 7 8} 1 2 3 4 5 6 7 8 % lappend list 9 10 can't set "list": assertion failed: 10<10 The error message isn't as clear as could be, because the [llength $list] is already substituted in it. But I couldn't find an easy solution to that quirk in this breakfast fun project - backslashing the $condition in the assertt code sure didn't help. Better ideas welcome.

To make the assertion condition more readable, we could quote the condition one more time,i.e In this case,when trace trigger fires, the argument for assert is {[llength $list]<10}.

In any case, these few lines of code give us a kind of bounds checking - the size of Tcl's data structures is in principle only bounded by the available virtual memory, but runaway loops may be harder to debug, compared to a few assertt calls for suspicious variables:

assertt aString {[string length $aString]<1024} or

assertt anArray {[array size anArray] < 1024*1024}

Tcllib has a control::assert with more bells and whistles.

A tiny testing framework
Bugs happen. The earlier found, the easier for the coder, so the golden rule "Test early. Test often" should really be applied.

One easy way is adding self-tests to a file of Tcl code. When the file is loaded as part of a library, just the proc definitions are executed. If however you feed this file directly to a tclsh, that fact is detected, and the "e.g." calls are executed. If the result is not the one expected, this is reported on stdout; and in the end, you even get a little statistics.

Here's a file that implements and demonstrates "e.g.":

if {[info exists argv0]&&[file tail [info script]] eq [file tail $argv0]} { set Ntest 0; set Nfail 0 proc e.g. {cmd -> expected} { incr ::Ntest catch {uplevel 1 $cmd} res if {$res ne $expected} { puts "$cmd -> $res, expected $expected" incr ::Nfail }   } } else {proc e.g. args {}} ;# does nothing, compiles to nothing
 * 1) PROLOG -- self-test: if this file is sourced at top level:

proc sum {a b} {expr {$a+$b}} e.g. {sum 3 4} -> 7
 * 1) - Your code goes here, with e.g. tests following

proc mul {a b} {expr {$a*$b}} e.g. {mul 7 6} -> 42

e.g. {expr 1/0} -> "divide by zero"
 * 1) testing a deliberate error (this way, it passes):

e.g. {puts "[info script] : tested $::Ntest, failed $::Nfail"} -> ""
 * 1) EPILOG -- show statistics:

Guarded proc
In more complex Tcl software, it may happen that a procedure is defined twice with different body and/or args, causing hard-to-track errors. The Tcl command proc itself doesn't complain if it is called with an existing name. Here is one way to add this functionality. Early in your code, you overload the proc command like this:

rename proc _proc _proc proc {name args body} { set ns [uplevel namespace current] if {[info commands $name]!="" || [info commands ${ns}::$name]!=""} { puts stderr "warning: [info script] redefines $name in $ns" } 	uplevel [list _proc $name $args $body] }

From the time that is sourced, any attempt to override a proc name will be reported to stderr (on Win-wish, it would show on the console in red). You may make it really strict by adding an "exit" after the "puts stderr ...", or throw an error.

Known feature: proc names with wildcards will run into this trap, e.g.

proc * args {expr [join $args *]*1} will always lead to a complaint because "*" fits any proc name. Fix (some regsub magic on 'name') left as an exercise.

Windows wish console
While on Unixes, the standard channels stdin, stdout, and stderr are the same as the terminal you started wish from, a Windows wish doesn't typically have these standard channels (and is mostly started with double-click anyway). To help this, a console was added that takes over the standard channels (stderr even coming in red, stdin in blue). The console is normally hidden, but can be brought up with the command

console show

You can also use the partially documented "console" command. "console eval " evals the given script in the Tcl interpreter that manages the console. The console's text area is actually a text widget created in this interpreter. For example:

console eval {.console config -font Times} will change the font of the console to "Times". Since the console is a Tk text widget, you can use all text widget commands and options on it (for example, changing colors, bindings...).

console eval {winfo children .} tells you more about the console widget: it is a toplevel with children .menu, .console (text), and .sb (scrollbar). You can resize the whole thing with

console eval {wm geometry. $Wx$H+$X+$Y} where $W and $H are dimensions in character cells (default 80x24), but $X and $Y are in pixels.

And more again: you can even add widgets to the console - try

console eval {pack [button .b -text hello -command {puts hello}]}

The button appears between the text widget and the scroll bar, and looks and does as expected. There is also a way back: the main interpreter is visible in the console interpreter under the name, consoleinterp.

Remote debugging
Here's a simple experiment on how to connect two Tcl processes so that one (call it "debugger") can inspect and control the other ("debuggee"). Both must have an event loop running (which is true when Tk runs, or when started with e.g. vwait forever).

As this goes over a socket connection, the two processes could be on different hosts and operating systems (though I've so far tested only the localhost variety). Use at your own risk, of course... :^)

The "debuggee" contains in my experiments the following code, in addition to its own:

proc remo_server { set sock [socket -server remo_accept $port] } proc remo_accept {socket adr port} { fileevent $socket readable [list remo_go $socket] } proc remo_go {sock} { gets $sock line catch {uplevel \#0 $line} res puts $sock $res if [catch {flush $sock}] {close $sock} } remo_server

The "debugger" in this version (remo.tcl) runs only on Windows in a wish, as it needs a console, but you could modify it to avoid these restrictions:

console show wm withdraw. set remo [socket localhost 3456] fileevent $remo readable "puts \[gets $remo\]" proc r args {puts $::remo [join $args]; flush $::remo} puts "remote connection ready - use r to talk"
 * 1) !/usr/bin/env wish

Now from remo you can call any Tcl command in the "debuggee", where it is executed in global scope, so in particular you can inspect (and modify) global variables. But you could also redefine procs on the fly, or whatever tickles your fancy... Examples from a remo session, showing that the two have different pids, how errors are reported, and that quoting is different from normal (needs more work):

10 % pid 600 11 % r pid 2556 12 % r wm title. "Under remote control" wrong # args: should be "wm title window ?newTitle?" 13 % r wm title. {"Under remote control"}

title: Tcl Programming/Debugging


text:
User:5ko

A Wikipedia user since 2003. Check out. Contact.

license: Creative Commons - Attribution Share-Alike - https://creativecommons.org/licenses/by-sa/4.0/

title: User:5ko


text:
Tcl Programming/Tk

Introduction
The Tk (Tool Kit) is the most popular Tcl extension for designing graphical user interfaces (GUI) on Macintosh, Unix/Linux, or Windows operating systems.

With little effort, it allows to put together useful
 * windows (forms, as some call them) consisting of
 * widgets, which are managed by
 * geometry managers. Also, you can easily define
 * bindings of mouse or keyboard events to trigger the actions you want.

Example: calculator
Here is a very simple, complete Tcl/Tk script that implements a calculator: package require Tk pack [entry .e -textvar e -width 50] bind .e  { set e [regsub { *=.*} $e ""] ;# remove evaluation (Chris) catch {expr [string map {/ *1./} $e]} res append e " = $res" } It creates an entry widget named .e, into which you can type from the keyboard, with an associated variable e (which will mirror the entry's content), and manages it with pack.

One binding is defined: if with keyboard focus on .e, the  key is hit, then
 * all division operators (/) in the variable e are mapped to "*1./" (this forces floating point division),
 * the resulting string is fed to expr to evaluate it as an arithmetic/logic expression
 * as there may be errors in the user input, the expr call is wrapped into a catch which assigns either the result of expr, or the error message if one occurred, into the variable res
 * the result of the last evaluation is cleared by deleting everything after =
 * finally, an equal sign and the value of the res variable are appended to e, making input and result immediately visible in the entry.

Example: a tiny IRC client
As before in the Tcl section, here's a working little script again: a client for IRC (Internet Relay Chat) in 38 lines of code, that features a text and an entry widget:

package require Tk set ::server irc.freenode.org set ::chan  #tcl set ::me    $tcl_platform(user) text .t -height 30 -wrap word -font {Arial 9} .t tag config bold  -font [linsert [.t cget -font] end bold] .t tag config italic -font [linsert [.t cget -font] end italic] .t tag config blue  -foreground blue entry .cmd pack .cmd -side bottom -fill x pack .t -fill both -expand 1 bind .cmd  post proc recv {} { gets $::fd line if {[regexp {:([^!]*)![^ ].* +PRIVMSG ([^ :]+) +:(.*)} $line -> \ nick target msg]} { set tag "" if [regexp {\001ACTION(.+)\001} $msg -> msg] {set tag italic} if [in {azbridge ijchain} $nick] {regexp {<([^>]+)>(.+)} $msg -> nick msg} .t insert end $nick\t bold $msg\n $tag } else {.t insert end $line\n italic} .t yview end } proc in {list element} {expr {[lsearch -exact $list $element]>=0}} proc post {} { set msg [.cmd get] if [regexp {^/me (.+)} $msg -> action] {set msg "\001ACTION $action\001"} foreach line [split $msg \n] {send "PRIVMSG $::chan :$line"} .cmd delete 0 end set tag "" if [regexp {\001ACTION(.+)\001} $msg -> msg] {set tag italic} .t insert end $::me\t {bold blue} $msg\n [list blue $tag] .t yview end } proc send str {puts $::fd $str; flush $::fd} set ::fd [socket $::server 6667] send "NICK $::me" send "USER $::me 0 * :PicoIRC user" send "JOIN $::chan" fileevent $::fd readable recv bind.  {exec wish $argv0 &; exit}

The last line is a quick debugging helper: if you modified the script in the editor, save to disk, then hit  in the app to start it anew.

Widgets
Widgets are GUI objects that, when mapped by a geometry manager, correspond to a rectangular area on the screen, with different properties and capabilities.

Widgets are named with path names, somewhat resembling file system path names, except that the separator for widgets is a period ".". For example, .foo.bar is a child of foo which is a child of "." Parent-child relation occurs typically with containers, e.g. toplevel, frame, canvas, text. The name parts (i.e. between the dots) can be almost any string that does not contain "." of course, or starts with a Capital Letter (this is because widget class names with capital initial have a special meaning, they denote class-wide options).

If you have a proc that takes a parent widget w and adds children, it may be important to distinguish whether w is "." or another - because you can't concatenate a child widget name directly to "." - $w.kid will make an invalid name if $w == ".". Here's how to avoid this: set w2 [expr {$w eq "."? "": $w}] button $w2.$kid ...

Widgets are created by a command named after their class, which then takes the path name (requiring that parent widgets have to exist by that time) and any number of -key value options that make up the original configuration, e.g. button .b -text "Hello!" -command {do something} After creation, communication with the widget goes via a created command that corresponds to its name. For instance, the configuration options can be queried set text [.b cget -text] or changed .b configure -text Goodbye! -background red Some "methods" like cget, configure are generic to all widget classes, others are specific to one or a few. For instance, both text and entry accept the insert method. See the manual pages for all the details.

Widgets appear on screen only after they have been given to a geometry manager (see more below). Example: text .t -wrap word pack .t -fill both -expand 1 As widget creation commands return the pathname, these two steps can also be nested like pack [text .t -wrap word] -fill both -expand 1

The destroy command deletes a widget and all of its child widgets, if present: destroy .b

The following sub-chapters describe the widgets available in Tk. -

button
With text and/or image, calls a configurable command when clicked. Example: button .b -text Hello! -command {puts "hello, world"}

canvas
Scrollable graphic surface for line, rectangle, polygon, oval, and text items, as well as bitmaps and photo images and whole embedded windows. See for example "A tiny drawing program" below. Example: pack [canvas .c -background white] .c create line 50 50 100 100 150 50 -fill red -width 3 .c create text 100 50 -text Example

Pan a canvas (scroll it inside its window with middle mouse-button held down) by inheriting the text widget bindings: bind .c <2> [bind Text <2>] bind .c  [bind Text ]

entry
One-line editable text field, horizontally scrollable (see example above). You can specify a validation function to constrain what is entered. Example: entry .e -width 20 -textvariable myVar set myVar "this text appears in the entry"

frame
Container for several widgets, often used with pack, or for wrapping "megawidgets"

label
One- or multiline field for text display, can be tied to a text variable to update when that variable changes. Linebreaks are specified by \n in the text to be displayed.

labelframe
A container similar to a frame, decorated with a thin rectangle around, and a label at top-left position. Example (a tiny radio band selector): pack [labelframe .lf -text Band] pack [radiobutton .lf.am -text AM -variable band -value AM] pack [radiobutton .lf.fm -text FM -variable band -value FM] set band AM

listbox
Multiline display of a list, scrollable. Single or multiple items can be selected with the mouse.

menu
To add a menu to a GUI application, take steps of three kinds: . configure -menu [menu .m] .m add cascade -label File -menu [menu .m.mFile] .m.mFile add command -label Open -command {openFile ...} .m.mFile add separator
 * Create the toplevel horizontal menu (needed only once):
 * For each item in the top menu, create a cascaded submenu, e.g.
 * For each entry in a submenu, add it like this:

As these commands are a bit verbose, one can wrap them into a little helper: proc m+ {head name {cmd ""}} { if {![winfo exists .m.m$head]} { .m add cascade -label $head -menu [menu .m.m$head -tearoff 0] }   if [regexp ^-+$ $name] { .m.m$head add separator } else {.m.m$head add command -label $name -comm $cmd} } Demo example - now menu items can be created in a much clearer way:

. configure -menu [menu .m] m+ File Open {.t insert end "opened\n"} m+ File Save {.t insert end "saved\n"} m+ File - m+ File Exit exit m+ Edit Cut ... pack [text .t -wrap word] -fill both -expand 1

radiobutton
A button with a selector field which can be on or off, and a label. Clicking the selector field with the mouse changes the value of an associated global variable. Typically, multiple radiobuttons are tied to the same variable. For examples, see labelframe above.

scrollbar
Horizontal or vertical scrollbars (vertical being the default, for horizontal specify: -orientation horizontal, or -ori hori if you like it short) can be tied to canvas, entry, listbox or text widgets. The interaction between a scrollbar and its scrolled widget goes with callbacks, in which one notifies the other: Arguments to these methods will be automatically added when the callbacks are invoked.
 * scrollbar to widget: xview or yview method
 * widget to scrollbar: set method

For example, here's how to connect a text widget with a vertical scrollbar: pack [scrollbar .y -command ".t yview"] -side right -fill y pack [text .t -wrap word -yscrollc ".y set"] \ -side right -fill both -expand 1

With most widgets, scrollbars adjust automatically to the widget's contents. For canvas widgets, you need to update the scrollregion after adding new items. most simply like this: $canvas configure -scrollregion [$canvas bbox all]

text
Scrollable editable multiline text with many formatting options. Can also contain images and embedded widgets. The default wrapping setting is "none", so you might need a horizontal scrollbar to see all of long lines. In many cases it's more user-friendly to configure a text widget as -wrap word - then you only need a vertical scrollbar at most.

Positions in a text widget are specified as line.column, where line starts from 1, and column from 0, so 1.0 is the very first character in a text widget. Example how to delete all contents: $t delete 1.0 end For highlighting part of the contents, you can define tags and assign them to subsequences: $t tag configure ul -underline 1 $t insert end "The next word is " {} underlined ul ", the rest is not."

toplevel
Standalone frame window, mostly with decorations (title bar, buttons) from the window manager. When you start Tk, you receive an initially empty toplevel named "." (one dot). If you want more toplevels, create them like this: toplevel .mySecondWindow Such toplevels are logically children of ".". To assign a nice title to a toplevel, use wm title $toplevel "This is the title" You can also control the geometry (size and position) of a toplevel with wm geometry $toplevel ${width}x$height+$x+$y

Geometry managers
The purpose of geometry managers is to compute the required height, width, and location of widgets, and map them on screen. Besides grid, pack and place, the canvas and text widgets can also manage embedded widgets.

Calls to geometry managers always start with the manager's name, then (mostly) one or more widget names, then any number of -name value options

grid
This geometry manager is best suited for tabular window layout consisting of rows and columns. Example, to put three widgets in a horizontal row: grid .1 .2 .3 -sticky news The -sticky option indicates what side of its box the widget should stick to, in compass direction; "news" is north-east-west-south", i.e. all four sides.

Here's a minimal solution to display a table (list of lists) in a grid of labels:

package require Tk proc table {w content args} { frame $w -bg black set r 0 foreach row $content { set fields {} set c 0 foreach col $row { lappend fields [label $w.$r/$c -text $col] incr c        } eval grid $fields -sticky news -padx 1 -pady 1 incr r    } set w }

table .t { {Row Head1 Head2} {1  foo   42} {2  bar   1234} {3  grill testing} } pack .t
 * 1) --- Test:

after 2000 .t.3/2 config -text Coucou
 * 1) --- Changing the contents, given row and column number:

pack
This used to be the workhorse manager, but in recent years has been less popular than grid. Anyway, it is still good for cases where you have widgets aligned in only one direction (horizontally or vertically). For more complex layouts, one used to insert intermediate frames, but grid makes such jobs just easier. Example: pack .x -fill both -expand 1 -side left

place
This geometry manager is not often used, mostly for special applications, like when you want to highlight the current tab of a tab notebook. It allows pixel-precise placement of widgets, but is less dynamic in reaction to resizing of the toplevel or inner widgets.

Dialogs
Dialogs are toplevels that are to tell a message, or answer a question. You don't have to assign a widget path name to them. Just call them as functions and evaluate the result (often "" if the dialog was canceled).

tk_getOpenFile
A file selector dialog (limited to existing files). Returns the selected file with path name, or "" if canceled.

tk_getSaveFile
A file selector dialog, which also allows specification of a not existing file. Returns the selected file with path name, or "" if canceled.

tk_messageBox
A simple dialog that displays a string and can be closed with an "OK" button. Example: tk_messageBox -message "hello, world!"

tk_chooseColor
Displays a dialog for color selection. The returned value is the selected color in one of the representations conformant to Tcl's comprehension of such information; on Microsoft Windows systems this might constitute a hexadecimal string in the format “#RRGGBB”. Upon abortion of the process, the empty string is instead delivered. The dialog may be configured to preselect a certain default color via the “-initialcolor” option, a subordination into a parent widget with “-parent”, and a title caption through “-title”. tk_chooseColor -initialcolor #FF0000 -parent. -title "What tincture do you wish?"

Custom dialogs
Besides the prefabricated dialogs that come with Tk, it's also not too hard to build custom ones. As a very simple example, here's a "value dialog" that prompts the user for to type in a value:

proc value_dialog {string} { set w [toplevel .[clock seconds]] wm resizable $w 0 0 wm title $w "Value request" label $w.l -text $string entry $w.e -textvar $w -bg white bind $w.e  {set done 1} button $w.ok    -text OK     -command {set done 1} button $w.c     -text Clear  -command "set $w {}" button $w.cancel -text Cancel -command "set $w {}; set done 1" grid $w.l -    -        -sticky news grid $w.e -    -        -sticky news grid $w.ok $w.c $w.cancel vwait done destroy $w set ::$w } Test: set test [value_dialog "Give me a value please:"] puts test:$test pack [ label .l -text "Value: '$test' " ]

For a more elaborate example, here is a record editor dialog (multiple fields, each with a label and entry (or text for multi-line input)): proc editRecord {title headers fields} { set oldfocus [focus] set w [toplevel .[clock clicks]] wm resizable $w 1 0 wm title $w $title set n 0 foreach h $headers f $fields { if ![regexp {(.+)([=+])} $h -> hdr type] {set hdr $h; set type ""} label $w.h$n -text $hdr -anchor ne        switch -- $type { = {label $w.e$n -width [string length $f] -text $f -anchor w -bg white} + {[text $w.e$n -width 20 -height 6] insert end $f} default {[entry $w.e$n -width [string length $f]] insert end $f} }        grid $w.h$n $w.e$n -sticky news incr n    } button $w.ok -text OK -width 5 -command [list set $w 1] button $w.cancel -text Cancel -command [list set $w 0] grid $w.ok $w.cancel -pady 5 grid columnconfigure $w 1 -weight 1 vwait ::$w if [set ::$w] { #-- collect the current entry contents set n 0 foreach h $headers f $fields { regexp {([^=+].+)([=+]?)} $h -> hdr type switch -- $type { "" {lappend res [$w.e$n get]} = {lappend res [$w.e$n cget -text]} + {lappend res [$w.e$n get 1.0 end]} }            incr n         } } else {set res {}} destroy $w unset ::$w ;#-- clean up the vwait variable focus $oldfocus return $res }

Quick test:

editRecord Test {foo= bar grill+} {one two three}

Megawidgets made easy
The term "megawidgets" is popular for compound widgets that in themselves contain other widgets, even though they will hardly number a million (what the prefix Mega- suggests), more often the child widgets' number will not exceed ten.

To create a megawidget, one needs one proc with the same signature as Tk widget creation commands. This proc will, when called, create another proc named after the widget, and dispatch methods either to specific handlers, or the generic widget command created by Tk.

A little notebook
Plain Tk does not contain a "notebook" widget, with labeled tabs on top that raise one of the "pages", but it's easy to make one. This example demonstrates how the tabs are implemented as buttons in a frame, and how the original Tk command named like the frame is "overloaded" to accept the additional add and raise methods:

proc notebook {w args} { frame $w pack [frame $w.top] -side top -fill x -anchor w   rename $w _$w proc $w {cmd args} { #-- overloaded frame command set w [lindex [info level 0] 0] switch -- $cmd { add    {notebook'add   $w $args} raise  {notebook'raise $w $args} default {eval [linsert $args 0 _$w $cmd]} }   }    return $w }

proc notebook'add {w title} { set btn [button $w.top.b$title -text $title -command [list $w raise $title]] pack $btn -side left -ipadx 5 set f [frame $w.f$title -relief raised -borderwidth 2] pack $f -fill both -expand 1 $btn invoke bind $btn <3> "destroy {$btn}; destroy {$f}" ;# (1) return $f }

proc notebook'raise {w title} { foreach i [winfo children $w.top] {$i config -borderwidth 0} $w.top.b$title config -borderwidth 1 set frame $w.f$title foreach i [winfo children $w] { if {![string match *top $i] && $i ne $frame} {pack forget $i} }   pack $frame -fill both -expand 1 }

Test and demo code:

package require Tk pack [notebook .n] -fill both -expand 1 set p1 [.n add Text] pack  [text $p1.t -wrap word] -fill both -expand 1 set p2 [.n add Canvas] pack  [canvas $p2.c -bg yellow] -fill both -expand 1 set p3 [.n add Options] pack  [button $p3.1 -text Console -command {console show}] .n raise Text wm geometry. 400x300

Binding events
Events within Tcl/Tk include actions performed by the user, such as pressing a key or clicking the mouse. To react to mouse and keyboard activity, the bind command is used. As shown in the calculator example:

The  keyword operates on   and associates the event related to the   event. The following bracket indicates a start of a set of procedures which are executed when the event is performed.

BWidget
BWidget is an extension to Tk written in pure Tcl (therefore it can even run on Windows Mobile-driven cell phones). It offers mega-widgets (all class names starting with Uppercase) like Screenshot of a NoteBook and a Tree, on a PocketPC under Windows/CE
 * ComboBox
 * NoteBook
 * Tree

Tree examples
Here is a "hello world" example of a Tree widget (this is a complete script). The root node is constantly called root, for the others you have to make up names: package require BWidget pack [Tree .t] .t insert end root n1 -text hello .t insert end root n2 -text world .t insert end n2  n21 -text (fr:monde) .t insert end n2  n22 -text (de:Welt) The famous typewriter test sentence represented as a syntax tree: package require BWidget pack [Tree .t -height 16] -fill both -expand 1 foreach {from to text} { root S S   S   np1  NP    S   vp   VP    np1 det1 Det:The np1 ap1 AP    ap1 adj1 Adj:quick ap1 adj2 Adj:brown ap1 n1  N:fox vp v    V:jumps vp pp   PP    pp  prep Prep:over pp np2  NP    np2 det2 Det:the np2 ap2 AP    ap2 adj3 Adj:lazy ap2 n2  N:dog } {.t insert end $from $to -text $text} .t opentree S

Colors
Colors in Tk can be specified in three ways: The last form is only returned by commands. To specify a color to a command, you'll have to hex-format it. For instance, white could be described as #FFFFFF.
 * a symbolic name, like: red green blue yellow magenta cyan
 * a hex string preceded by a #: #RGB, #RRGGBB, #RRRRGGGGBBBB
 * a list of three non-negative integers

To turn a symbolic name into its RGB components: winfo rgb. $colorname

Here is the list of defined color names (as from X11's rgb.txt): set COLORS { snow {ghost white} {white smoke} gainsboro {floral white} {old lace} linen {antique white} {papaya whip} {blanched almond} bisque {peach puff} {navajo white} moccasin cornsilk ivory {lemon chiffon} seashell honeydew {mint cream} azure {alice blue} lavender {lavender blush} {misty rose} white black {dark slate gray} {dim gray} {slate gray} {light slate gray} gray {light grey} {midnight blue} navy {cornflower blue} {dark slate blue} {slate blue} {medium slate blue} {light slate blue} {medium blue} {royal blue} blue {dodger blue} {deep sky blue} {sky blue} {light sky blue} {steel blue} {light steel blue} {light blue} {powder blue} {pale turquoise} {dark turquoise} {medium turquoise} turquoise cyan {light cyan} {cadet blue} {medium aquamarine} aquamarine {dark green} {dark olive green} {dark sea green} {sea green} {medium sea green} {light sea green} {pale green} {spring green} {lawn green} green chartreuse {medium spring green} {green yellow} {lime green} {yellow green} {forest green} {olive drab} {dark khaki} khaki {pale goldenrod} {light goldenrod yellow} {light yellow} yellow gold {light goldenrod} goldenrod {dark goldenrod} {rosy brown} {indian red} {saddle brown} sienna peru burlywood beige wheat {sandy brown} tan chocolate firebrick brown {dark salmon} salmon {light salmon} orange {dark orange} coral {light coral} tomato {orange red} red {hot pink} {deep pink} pink {light pink} {pale violet red} maroon {medium violet red} {violet red} magenta violet plum orchid {medium orchid} {dark orchid} {dark violet} {blue violet} purple {medium purple} thistle snow2 snow3 snow4 seashell2 seashell3 seashell4 AntiqueWhite1 AntiqueWhite2 AntiqueWhite3 AntiqueWhite4 bisque2 bisque3 bisque4 PeachPuff2 PeachPuff3 PeachPuff4 NavajoWhite2 NavajoWhite3 NavajoWhite4 LemonChiffon2 LemonChiffon3 LemonChiffon4 cornsilk2 cornsilk3 cornsilk4 ivory2 ivory3 ivory4 honeydew2 honeydew3 honeydew4 LavenderBlush2 LavenderBlush3 LavenderBlush4 MistyRose2 MistyRose3 MistyRose4 azure2 azure3 azure4 SlateBlue1 SlateBlue2 SlateBlue3 SlateBlue4 RoyalBlue1 RoyalBlue2 RoyalBlue3 RoyalBlue4 blue2 blue4 DodgerBlue2 DodgerBlue3 DodgerBlue4 SteelBlue1 SteelBlue2 SteelBlue3 SteelBlue4 DeepSkyBlue2 DeepSkyBlue3 DeepSkyBlue4 SkyBlue1 SkyBlue2 SkyBlue3 SkyBlue4 LightSkyBlue1 LightSkyBlue2 LightSkyBlue3 LightSkyBlue4 SlateGray1 SlateGray2 SlateGray3 SlateGray4 LightSteelBlue1 LightSteelBlue2 LightSteelBlue3 LightSteelBlue4 LightBlue1 LightBlue2 LightBlue3 LightBlue4 LightCyan2 LightCyan3 LightCyan4 PaleTurquoise1 PaleTurquoise2 PaleTurquoise3 PaleTurquoise4 CadetBlue1 CadetBlue2 CadetBlue3 CadetBlue4 turquoise1 turquoise2 turquoise3 turquoise4 cyan2 cyan3 cyan4 DarkSlateGray1 DarkSlateGray2 DarkSlateGray3 DarkSlateGray4 aquamarine2 aquamarine4 DarkSeaGreen1 DarkSeaGreen2 DarkSeaGreen3 DarkSeaGreen4 SeaGreen1 SeaGreen2 SeaGreen3 PaleGreen1 PaleGreen2 PaleGreen3 PaleGreen4 SpringGreen2 SpringGreen3 SpringGreen4 green2 green3 green4 chartreuse2 chartreuse3 chartreuse4 OliveDrab1 OliveDrab2 OliveDrab4 DarkOliveGreen1 DarkOliveGreen2 DarkOliveGreen3 DarkOliveGreen4 khaki1 khaki2 khaki3 khaki4 LightGoldenrod1 LightGoldenrod2 LightGoldenrod3 LightGoldenrod4 LightYellow2 LightYellow3 LightYellow4 yellow2 yellow3 yellow4 gold2 gold3 gold4 goldenrod1 goldenrod2 goldenrod3 goldenrod4 DarkGoldenrod1 DarkGoldenrod2 DarkGoldenrod3 DarkGoldenrod4 RosyBrown1 RosyBrown2 RosyBrown3 RosyBrown4 IndianRed1 IndianRed2 IndianRed3 IndianRed4 sienna1 sienna2 sienna3 sienna4 burlywood1 burlywood2 burlywood3 burlywood4 wheat1 wheat2 wheat3 wheat4 tan1 tan2 tan4 chocolate1 chocolate2 chocolate3 firebrick1 firebrick2 firebrick3 firebrick4 brown1 brown2 brown3 brown4 salmon1 salmon2 salmon3 salmon4 LightSalmon2 LightSalmon3 LightSalmon4 orange2 orange3 orange4 DarkOrange1 DarkOrange2 DarkOrange3 DarkOrange4 coral1 coral2 coral3 coral4 tomato2 tomato3 tomato4 OrangeRed2 OrangeRed3 OrangeRed4 red2 red3 red4 DeepPink2 DeepPink3 DeepPink4 HotPink1 HotPink2 HotPink3 HotPink4 pink1 pink2 pink3 pink4 LightPink1 LightPink2 LightPink3 LightPink4 PaleVioletRed1 PaleVioletRed2 PaleVioletRed3 PaleVioletRed4 maroon1 maroon2 maroon3 maroon4 VioletRed1 VioletRed2 VioletRed3 VioletRed4 magenta2 magenta3 magenta4 orchid1 orchid2 orchid3 orchid4 plum1 plum2 plum3 plum4 MediumOrchid1 MediumOrchid2 MediumOrchid3 MediumOrchid4 DarkOrchid1 DarkOrchid2 DarkOrchid3 DarkOrchid4 purple1 purple2 purple3 purple4 MediumPurple1 MediumPurple2 MediumPurple3 MediumPurple4 thistle1 thistle2 thistle3 thistle4 gray1 gray2 gray3 gray4 gray5 gray6 gray7 gray8 gray9 gray10 gray11 gray12 gray13 gray14 gray15 gray16 gray17 gray18 gray19 gray20 gray21 gray22 gray23 gray24 gray25 gray26 gray27 gray28 gray29 gray30 gray31 gray32 gray33 gray34 gray35 gray36 gray37 gray38 gray39 gray40 gray42 gray43 gray44 gray45 gray46 gray47 gray48 gray49 gray50 gray51 gray52 gray53 gray54 gray55 gray56 gray57 gray58 gray59 gray60 gray61 gray62 gray63 gray64 gray65 gray66 gray67 gray68 gray69 gray70 gray71 gray72 gray73 gray74 gray75 gray76 gray77 gray78 gray79 gray80 gray81 gray82 gray83 gray84 gray85 gray86 gray87 gray88 gray89 gray90 gray91 gray92 gray93 gray94 gray95 gray97 gray98 gray99 } In addition, the following are defined on Windows: set WINDOWSCOLORS { SystemButtonFace SystemButtonText SystemDisabledText SystemHighlight SystemHightlightText SystemMenu SystemMenuText SystemScrollbar SystemWindow SystemWindowFrame SystemWindowText }

Cursors
For every widget, you can specify how the mouse cursor should look when over it. Here's the list of defined cursor names: set cursors { X_cursor arrow based_arrow_down based_arrow_up boat bogosity bottom_left_corner bottom_right_corner bottom_side bottom_tee box_spiral center_ptr circle clock coffee_mug cross cross_reverse crosshair diamond_cross dot dotbox double_arrow draft_large draft_small draped_box exchange fleur gobbler gumby hand1 hand2 heart icon iron_cross left_ptr left_side left_tee leftbutton ll_angle lr_angle man middlebutton mouse pencil pirate plus question_arrow right_ptr right_side right_tee rightbutton rtl_logo sailboat sb_down_arrow sb_h_double_arrow sb_left_arrow sb_right_arrow sb_up_arrow sb_v_double_arrow shuttle sizing spider spraycan star target tcross top_left_arrow top_left_corner top_right_corner top_side top_tee trek ul_angle umbrella ur_angle watch xterm } A little tool that presents the cursor names, and shows each cursor shape when mousing over: set ncols 4 for {set i 0} {$i<$ncols} {incr i} { lappend cols col$i } set nmax [expr {int([llength $cursors]*1./$ncols)}] foreach col $cols { set $col [lrange $cursors 0 $nmax] set cursors [lrange $cursors [expr $nmax+1] end] } label .top -text "Move the cursor over a name to see how it looks" \ -relief ridge grid .top -columnspan $ncols -sticky news -ipady 2 for {set i 0} {$i<[llength $col0]} {incr i} { set row {} foreach col $cols { set name [lindex [set $col] $i] if {$name eq ""} break lappend row .l$name label .l$name -text $name -anchor w       bind .l$name  [list %W config -cursor $name] }   eval grid $row -sticky we }

Fonts
Fonts are provided by the windowing system. Which are available depends on the local installation. Find out which fonts are available with font families

The typical description of a font is a list of up to three elements: family size ?style? Example: set f {{Bitstream Cyberbit} 10 bold} Family is a name like Courier, Helvetica, Times, ... Best pick one of the names delivered by font families, though there may be some mappings like "Helvetica" -> "Arial"

Size is point size (a typographer's point is 1/72th of an inch) if positive, or pixel size if negative. Normal display fonts often have a size of 9 or 10.

Style can be a list of zero or more of bold, italic, underlined, ...

Images: photos and bitmaps
Tk allows simple yet powerful operations on images. These come in two varieties: bitmaps and photos. Bitmaps are rather limited in functionality, they can be specified in XBM format, and rendered in configurable colors.

Photos have much more possibilities - you can load and save them in different file formats (Tk itself supports PPM and GIF - for others, use the Img extension), copy them with many options, like scaling/subsampling or mirroring, and get or set the color of single pixels.

Setting can also do rectangular regions in one go, as the following example shall demonstrate that creates a photo image of a tricolore flag (three even-spaced vertical bands - like France, Italy, Belgium, Ireland and many more). The default is France. You can specify the width, the height will be 2/3 of that. The procedure returns the image name - just save it in -format GIF if you want:

proc tricolore {w {colors {blue white red}}} { set im [image create photo] set fromx 0 set dx [expr $w/3] set tox $dx set toy [expr $w*2/3] foreach color $colors { $im put $color -to $fromx 0 $tox $toy incr fromx $dx; incr tox $dx }   set im }

pack [canvas .c -width 200 -height 200 -background grey] .c create image 100 100 -image [tricolore 150]
 * 1) Test - display flag on canvas:

[tricolore 300] write tric.gif -format gif
 * 1) Test - save image of flag to file:

Debugging Tk programs
A Tk program under development can be very rapidly debugged by adding such bindings:

bind.  {console show} This works only on Windows and Macintosh (pre-OS-X) and brings up a console in which you can interact with the Tcl interpreter, inspect or modify global variables, configure widgets, etc.

bind.  {eval [list exec wish $argv0] $argv &; exit} This starts a new instance of the current program (assuming you edited a source file and saved it to disk), and then terminates the current instance.

For short debugging output, one can also use the window's title bar. For example, to display the current mouse coordinates when it moves: bind.  {wm title. %X/%Y}

Other languages
Other programming languages have modules that interface and use Tcl/Tk:
 * In R (programming language), there's a tcltk library, invoked with the command library(tcltk)
 * In Python, there's a tkinter module, invoked with import tkinter or from tkinter import *
 * Common Lisp can communicate with Tcl/Tk via several externally available libraries, including CL-TK and LTK

title: Tcl Programming/Tk


text:
Talk:C++ Programming/Operators/Operator Overloading

overloading operators through friend functions
This article isn't very structured and it lacks some basic info like overloading operators through friend functions. It would be nice if there was something written about that. Mecanismo 14:58, 22 August 2007 (UTC)

 * This appears to have been addressed. See Overloadable Operators: Bitwise operators. Kmote (talk) 16:39, 14 November 2008 (UTC)

Overloadable Operators: Bitwise operators (typo)
There is a typo in item #1 describing the shift operators. I'd fix it myself, but I can't quite figure out what it's trying to say. Kmote (talk) 16:39, 14 November 2008 (UTC)

m_ThreadReceiver.compare(name)
0 == An unregistered user is having difficulties understanding why this solution when dealing with const char *name is superior. I have attempted to explain that since in this method we are dealing with two different types of variables the use of the std:string.compare guarantees that the code will perform for every possible value. --Panic (discuss • contribs) 19:47, 19 March 2011 (UTC)
 * That doesn't make sense. What is "perform for every possible value"? (Do you think it would work for some values and not others? I have the most trouble understanding this part of your statement, because in C++, for an operator involving a class, it either doesn't compile at all, or if it does, then somebody explicitly implemented an operator overload, in which case they designed it to always work.) And what does this have to do with the fact that they are two different types? In the preceding  method, that takes a , why are you willing to use   and not   instead? Why the inconsistency? Perhaps you are just familiar with some string operators and not others. If that is the case, let me inform you: all the relational operators work the same for two  , as it does for a   and a C string. --98.210.210.193 (discuss) 20:08, 19 March 2011 (UTC)
 * Did you try to pass a char* name = NULL as an argument using simply the m_ThreadReceiver == name as I indicated ? It breaks the method doesn't it? So it becomes evident that by using the m_ThreadReceiver.compare(name)==0 you guarantee type safety without any specific cost, and so it is a superior solution.
 * Your proposed change would work most of the time and depending on the implementation and guarantees you could happily live with that limitation, but as teaching material we should aim to provide the best option and permit clear understanding. Consistency is important but in this particular situation it doesn't apply since the method is target to a specific and different input. --Panic (discuss • contribs) 20:27, 19 March 2011 (UTC)
 * m_ThreadReceiver.compare(name) equally does not work if name is NULL --67.180.77.119 (discuss) 23:49, 19 March 2011 (UTC)
 * Hic, you are correct. I had done a test and gotten the idea that it would perform differently... --Panic (discuss • contribs) 04:21, 20 March 2011 (UTC)


text:
Tcl Programming/Introduction

So what is Tcl?
The name Tcl is derived from "Tool Command Language" and is pronounced "tickle". Tcl is a radically simple open-source interpreted programming language that provides common facilities such as variables, procedures, and control structures as well as many useful features that are not found in any other major language. Tcl runs on almost all modern operating systems such as Unix, Macintosh, and Windows (including Windows Mobile).

While Tcl is flexible enough to be used in almost any application imaginable, it does excel in a few key areas, including: automated interaction with external programs, embedding as a library into application programs, language design, and general scripting.

Tcl was created in 1988 by John Ousterhout and is distributed under a BSD style license (which allows you everything GPL does, plus closing your source code). The current stable version, in February 2008, is 8.5.1 (8.4.18 in the older 8.4 branch).

The first major GUI extension that works with Tcl is Tk, a toolkit that aims to rapid GUI development. That is why Tcl is now more commonly called Tcl/Tk.

The language features far-reaching introspection, and the syntax, while simple, is very different from the Fortran/Algol/C++/Java world. Although Tcl is a string based language there are quite a few object-oriented extensions for it like Snit, incr Tcl, and XOTcl to name a few.

Tcl was originally developed as a reusable command language for experimental computer aided design (CAD) tools. The interpreter is implemented as a C library that could be linked into any application. It is very easy to add new functions to the Tcl interpreter, so it is an ideal reusable "macro language" that can be integrated into many applications.

However, Tcl is a programming language in its own right, which can be roughly described as a cross-breed between
 * LISP/Scheme (mainly for its tail-recursion capabilities),
 * C (control structure keywords, expr syntax) and
 * Unix shells (but with more powerful structuring).

One language, many styles
Although a language where "everything is a command" appears like it must be "imperative" and "procedural", the flexibility of Tcl allows one to use functional or object-oriented styles of programming very easily. See "Tcl examples" below for ideas what one can do.

The traditional, "procedural" approach would be

Here is yet another style (not very fast on long lists, but depends on nothing but Tcl). It works by building up an expression, where the elements of the lists are joined with a plus sign, and then evaluating that:

From Tcl 8.5, with math operators exposed as commands, and the expand operator, this style is better:

or, if you have imported the tcl::mathop operators, just

Note that all of the above are valid stand alone Tcl scripts.

It is also very easy to implement other programming languages (be they (reverse) polish notation, or whatever) in Tcl for experimenting. One might call Tcl a "CS Lab". For instance, here's how to compute the average of a list of numbers in Tcl (after first writing somewhat more Tcl to implement a J-like functional language - see Tacit programming in examples):

or, one could implement a RPN language similar to FORTH or Postscript and write:

A more practical aspect is that Tcl is very open for "language-oriented programming" - when solving a problem, specify a (little) language which most simply describes and solves that problem - then go implement that language...

Why should I use Tcl?
Good question. The general recommendation is: "Use the best tool for the job". A good craftsman has a good set of tools, and knows how to use them best.

Tcl is a competitor to other scripting languages like awk, Perl, Python, PHP, Visual Basic, Lua, Ruby, and whatever else will come along. Each of these has strengths and weaknesses, and when some are similar in suitability, it finally becomes a matter of taste.

Points in favour of Tcl are:
 * simplest syntax (which can be easily extended)
 * cross-platform availability: Mac, Unix, Windows, ...
 * strong internationalization support: everything is a Unicode string
 * robust, well-tested code base
 * the Tk GUI toolkit speaks Tcl natively
 * BSD license, which allows open-source use like GPL, as well as closed-source
 * a very helpful community, reachable via newsgroup, Wiki, or chat :)

Tcl is not the best solution for every problem. It is however a valuable experience to find out what is possible with Tcl.

Example: a tiny web server
Before spoon-feeding the bits and pieces of Tcl, a slightly longer example might be appropriate, just so you get the feeling how it looks. The following is, in 41 lines of code, a complete little web server that serves static content (HTML pages, images), but also provides a subset of CGI functionality: if an URL ends with .tcl, a Tcl interpreter is called with it, and the results (a dynamically generated HTML page) served.

Note that no extension package was needed - Tcl can, with the socket command, do such tasks already pretty nicely. A socket is a channel that can be written to with puts. The fcopy copies asynchronously (in the background) from one channel to another, where the source is either a process pipe (the "exec tclsh" part) or an open file.

This server was tested to work pretty well even on 200MHz Windows 95 over a 56k modem, and serving several clients concurrently. Also, because of the brevity of the code, this is an educational example for how (part of) HTTP works.

And here's a little "CGI" script I tested it with (save as time.tcl):

Where to get Tcl/Tk
On most Linux systems, Tcl/Tk is already installed. You can find out by typing tclsh at a console prompt (xterm or such). If a "%" prompt appears, you're already set. Just to make sure, type info pa at the % prompt to see the patchlevel (e.g. 8.4.9) and info na to see where the executable is located in the file system.

Tcl is an open source project. The sources are available from http://tcl.sourceforge.net/ if you want to build it yourself.

For all major platforms, you can download a binary ActiveTcl distribution from ActiveState. Besides Tcl and Tk, this also contains many popular extensions - it's called the canonical "Batteries Included" distribution.

Alternatively, you can get Tclkit: a Tcl/Tk installation wrapped in a single file, which you don't need to unwrap. When run, the file mounts itself as a virtual file system, allowing access to all its parts.

January 2006, saw the release of a new and promising one-file vfs distribution of Tcl; eTcl. Free binaries for Linux, Windows, and Windows Mobile 2003 can be downloaded from http://www.evolane.com/software/etcl/index.html. Especially on PocketPCs, this provides several features that have so far been missing from other ports: sockets, window "retreat", and can be extended by providing a startup script, and by installing pure-Tcl libraries.

First steps
To see whether your installation works, you might save the following text to a file hello.tcl and run it (type tclsh hello.tcl at a console on Linux, double-click on Windows):

It should bring up a little grey window with the greeting.

To make a script directly executable (on Unix/Linux, and Cygwin on Windows), use this first line (the # being flush left):

or (in an older, deprecated tricky style):

This way, the shell can determine which executable to run the script with.

An even simpler way, and highly recommended for beginners as well as experienced users, is to start up tclsh or wish interactively. You will see a % prompt in the console, can type commands to it, and watch its responses. Even error messages are very helpful here, and don't cause a program abort - don't be afraid to try whatever you like! Example: $ tclsh 8.4.12 42 divide by zero You can even write programs interactively, best as one-liners: 120 For more examples, see the chapter "A quick tour".

Syntax
Syntax is just the rules how a language is structured. A simple syntax of English could say (ignoring punctuation for the moment): Simple as this is, it also describes Tcl's syntax very well - if you say "script" for "text", and "command" for "sentence". There's also the difference that a Tcl word can again contain a script or a command. So
 * A text consists of one or more sentences
 * A sentence consists of one or more words

is a command consisting of three words: if, a condition in braces, a command (also consisting of three words) in braces.

is a well-formed Tcl command: it calls Take (which must have been defined before) with the three arguments "this", "for", and "example". It is up to the command how it interprets its arguments, e.g.

will write the string "acos(-1)" to the stdout channel, and return the empty string "", while

will compute the arc cosine of -1 and return 3.14159265359 (an approximation of Pi), or

will invoke the string command, which again dispatches to its length sub-command, which determines the length of the second argument and returns 8.

Quick summary
A Tcl script is a string that is a sequence of commands, separated by newlines or semicolons.

A command is a string that is a list of words, separated by blanks. The first word is the name of the command, the other words are passed to it as its arguments. In Tcl, "everything is a command" - even what in other languages would be called declaration, definition, or control structure. A command can interpret its arguments in any way it wants - in particular, it can implement a different language, like expr.

A word is a string that is a simple word, or one that begins with { and ends with the matching } (braces), or one that begins with " and ends with the matching ". Braced words are not evaluated by the parser. In quoted words, substitutions can occur before the command is called: puts "Guten Morgen, ${Schüler}!" If the code would say $Schüler, this would be parsed as the value of variable $Sch, immediately followed by the constant string üler.
 * $[A-Za-z0-9_]+ substitutes the value of the given variable. Or, if the variable name contains characters outside that regular expression, another layer of bracing helps the parser to get it right:

 * (Part of) a word can be an embedded script: a string in [] brackets whose contents are evaluated as a script (see above) before the current command is called.

In short: Scripts and commands contain words. Words can again contain scripts and commands. (This can lead to words more than a page long...)

Arithmetic and logic expressions are not part of the Tcl language itself, but the language of the expr command (also used in some arguments of the if, for, while commands) is basically equivalent to C's expressions, with infix operators and functions. See separate chapter on expr below.

The man page: 11 rules
Here is the complete manpage for Tcl (8.4) with the "endekalogue", the 11 rules. (From 8.5 onward there is a twelfth rule regarding the {*} feature).

The following rules define the syntax and semantics of the Tcl language:

(1) Commands A Tcl script is a string containing one or more commands. Semi-colons and newlines are command separators unless quoted as described below. Close brackets are command terminators during command substitution (see below) unless quoted.

(2) Evaluation A command is evaluated in two steps. First, the Tcl interpreter breaks the command into words and performs substitutions as described below. These substitutions are performed in the same way for all commands. The first word is used to locate a command procedure to carry out the command, then all of the words of the command are passed to the command procedure. The command procedure is free to interpret each of its words in any way it likes, such as an integer, variable name, list, or Tcl script. Different commands interpret their words differently.

(3) Words Words of a command are separated by white space (except for newlines, which are command separators).

(4) Double quotes If the first character of a word is double-quote (") then the word is terminated by the next double-quote character. If semi-colons, close brackets, or white space characters (including newlines) appear between the quotes then they are treated as ordinary characters and included in the word. Command substitution, variable substitution, and backslash substitution are performed on the characters between the quotes as described below. The double-quotes are not retained as part of the word.

(5) Braces If the first character of a word is an open brace ({) then the word is terminated by the matching close brace (}). Braces nest within the word: for each additional open brace there must be an additional close brace (however, if an open brace or close brace within the word is quoted with a backslash then it is not counted in locating the matching close brace). No substitutions are performed on the characters between the braces except for backslash-newline substitutions described below, nor do semi-colons, newlines, close brackets, or white space receive any special interpretation. The word will consist of exactly the characters between the outer braces, not including the braces themselves.

(6) Command substitution If a word contains an open bracket ([) then Tcl performs command substitution. To do this it invokes the Tcl interpreter recursively to process the characters following the open bracket as a Tcl script. The script may contain any number of commands and must be terminated by a close bracket ( ] ). The result of the script (i.e. the result of its last command) is substituted into the word in place of the brackets and all of the characters between them. There may be any number of command substitutions in a single word. Command substitution is not performed on words enclosed in braces.

(7) Variable substitution If a word contains a dollar-sign ($) then Tcl performs variable substitution: the dollar-sign and the following characters are replaced in the word by the value of a variable. Variable substitution may take any of the following forms:

$name

Name is the name of a scalar variable; the name is a sequence of one or more characters that are a letter, digit, underscore, or namespace separators (two or more colons).

$name(index)

Name gives the name of an array variable and index gives the name of an element within that array. Name must contain only letters, digits, underscores, and namespace separators, and may be an empty string. Command substitutions, variable substitutions, and backslash substitutions are performed on the characters of index.

${name}

Name is the name of a scalar variable. It may contain any characters whatsoever except for close braces. There may be any number of variable substitutions in a single word. Variable substitution is not performed on words enclosed in braces.

(8) Backslash substitution If a backslash (\) appears within a word then backslash substitution occurs. In all cases but those described below the backslash is dropped and the following character is treated as an ordinary character and included in the word. This allows characters such as double quotes, close brackets, and dollar signs to be included in words without triggering special processing. The following table lists the backslash sequences that are handled specially, along with the value that replaces each sequence.
 * \a
 * Audible alert (bell) (0x7).

 * \b
 * Backspace (0x8).

 * \f
 * Form feed (0xc).

 * \n
 * Newline (0xa).

 * \r
 * Carriage-return (0xd).

 * \t
 * Tab (0x9).

 * \v
 * Vertical tab (0xb).

 * \ whiteSpace
 * A single space character replaces the backslash, newline, and all spaces and tabs after the newline. This backslash sequence is unique in that it is replaced in a separate pre-pass before the command is actually parsed. This means that it will be replaced even when it occurs between braces, and the resulting space will be treated as a word separator if it isn't in braces or quotes.

 * Literal backslash (\), no special effect.
 * Literal backslash (\), no special effect.

 * \ooo
 * The digits ooo (one, two, or three of them) give an eight-bit octal value for the Unicode character that will be inserted. The upper bits of the Unicode character will be 0.

 * \xhh
 * The hexadecimal digits hh give an eight-bit hexadecimal value for the Unicode character that will be inserted. Any number of hexadecimal digits may be present; however, all but the last two are ignored (the result is always a one-byte quantity). The upper bits of the Unicode character will be 0.

 * \uhhhh
 * The hexadecimal digits hhhh (one, two, three, or four of them) give a sixteen-bit hexadecimal value for the Unicode character that will be inserted.

Backslash substitution is not performed on words enclosed in braces, except for backslash-newline as described above.

(9) Comments If a hash character (#) appears at a point where Tcl is expecting the first character of the first word of a command, then the hash character and the characters that follow it, up through the next newline, are treated as a comment and ignored. The comment character only has significance when it appears at the beginning of a command.

(10) Order of substitution Each character is processed exactly once by the Tcl interpreter as part of creating the words of a command. For example, if variable substitution occurs then no further substitutions are performed on the value of the variable; the value is inserted into the word verbatim. If command substitution occurs then the nested command is processed entirely by the recursive call to the Tcl interpreter; no substitutions are performed before making the recursive call and no additional substitutions are performed on the result of the nested script. Substitutions take place from left to right, and each substitution is evaluated completely before attempting to evaluate the next. Thus, a sequence like

will always set the variable y to the value, 012.

(11) Substitution and word boundaries Substitutions do not affect the word boundaries of a command. For example, during variable substitution the entire value of the variable becomes part of a single word, even if the variable's value contains spaces.

Comments
The first rule for comments is simple: comments start with # where the first word of a command is expected, and continue to the end of line (which can be extended, by a trailing backslash, to the following line):

One of the problems new users of Tcl meet sooner or later is that comments behave in an unexpected way. For example, if you comment out part of code like this:

This happens to work, but any unbalanced braces in comments may lead to unexpected syntax errors. The reason is that Tcl's grouping (determining word boundaries) happens before the # characters are considered.

To add a comment behind a command on the same line, just add a semicolon:

Comments are only taken as such where a command is expected. In data (like the comparison values in switch), a # is just a literal character:

To comment out multiple lines of code, it is easiest to use "if 0":

Data types
In Tcl, all values are strings, and the phrase "Everything is a string" is often used to illustrate this fact. But just as 2 can be interpreted in English as "the number 2" or "the character representing the number 2", two different functions in Tcl can interpret the same value in two different ways. The command, for example, interprets "2" as a number, but the command   interprets "2" as a single character. All values in Tcl can be interpreted either as characters or something else that the characters represent. The important thing to remember is that every value in Tcl is a string of characters, and each string of characters might be interpreted as something else, depending on the context. This will become more clear in the examples below. For performance reasons, versions of Tcl since 8.0 keep track of both the string value and how that string value was last interpreted. This section covers the various "types" of things that Tcl values (strings) get interpreted as.

Strings
A string is a sequence of zero or more characters (where all 16-bit Unicodes are accepted in almost all situations, see in more detail below). The size of strings is automatically administered, so you only have to worry about that if the string length exceeds the virtual memory size.

In contrast to many other languages, strings in Tcl don't need quotes for markup. The following is perfectly valid:

Quotes (or braces) are rather used for grouping:

The difference is that inside quotes, substitutions (like of variables, embedded commands, or backslashes) are performed, while in braces, they are not (similar to single quotes in shells, but nestable):

In source code, quoted or braced strings can span multiple lines, and the physical newlines are part of the string too:

To reverse a string, we let an index i first point at its end, and decrementing i until it's zero, append the indexed character to the end of the result res:

Hex-dumping a string:

Finding a substring in a string can be done in various ways:

The matching is done with exact match in string first, with glob-style match in string match, and as a regular expression in regexp. If there are characters in substr that are special to glob or regular expressions, using string first is recommended.

Lists
Many strings are also well-formed lists. Every simple word is a list of length one, and elements of longer lists are separated by whitespace. For instance, a string that corresponds to a list of three elements:

Strings with unbalanced quotes or braces, or non-space characters directly following closing braces, cannot be parsed as lists directly. You can explicitly split them to make a list.

The "constructor" for lists is of course called list. It's recommended to use when elements come from variable or command substitution (braces won't do that). As Tcl commands are lists anyway, the following is a full substitute for the list command:

Lists can contain lists again, to any depth, which makes modelling of matrixes and trees easy. Here's a string that represents a 4 x 4 unit matrix as a list of lists. The outer braces group the entire thing into one string, which includes the literal inner braces and whitespace, including the literal newlines. The list parser then interprets the inner braces as delimiting nested lists.

The newlines are valid list element separators, too.

Tcl's list operations are demonstrated in some examples:

Note that only lappend, above is mutating. To change an element of a list (of a list...) in place, the lset command is useful - just give as many indexes as needed:

 </dd></dl>

The lindex command also takes multiple indexes:

<dl><dd> </dd></dl>

Example: To find out whether an element is contained in a list (from Tcl 8.5, there's the in operator for that):

<dl><dd> </dd></dl>

<dl><dd> </dd></dl>

Example: remove an element from a list variable by value (converse to lappend), if present:

<dl><dd> </dd></dl>

<dl><dd> </dd></dl>

<dl><dd> </dd></dl>

A simpler alternative, which also removes all occurrences of el:

Example: To draw a random element from a list L, we first determine its length (using llength), multiply that with a random number > 0.0 and < 1.0, truncate that to integer (so it lies between 0 and length-1), and use that for indexing (lindex) into the list:

Example: Transposing a matrix (swapping rows and columns), using integers as generated variable names:

<dl><dd> </dd></dl>

Example: pretty-printing a list of lists which represents a table:

Testing:

<dl><dd> </dd></dl>

Enumerations: Lists can also be used to implement enumerations (mappings from symbols to non-negative integers). Example for a nice wrapper around lsearch/lindex:

This assigns "apple" to 0, "blueberry" to 1, etc.

<dl><dd> </dd></dl>

<dl><dd> </dd></dl>

Numbers
Numbers are strings that can be parsed as such. Tcl supports integers (32-bit or even 64-bit wide) and "double" floating-point numbers. From Tcl 8.5 on, bignums (integers of arbitrarily large precision) are supported. Arithmetics is done with the expr command, which takes basically the same syntax of operators (including ternary x?y:z), parens, and math functions as C. See below for detailed discussion of expr.

Control the display format of numbers with the format command which does appropriate rounding:

<dl><dd> </dd></dl>

<dl><dd> </dd></dl>

Up to the 8.4 version (the present version is 8.5), Tcl honored the C convention that an integer starting with 0 is parsed as octal, so 0377 == 0xFF == 255 This changes in 8.5, though - too often people stumbled over "08" meant as hour or month, raised a syntax error, because 8 is no valid octal number. In the future you'd have to write 0o377 if you really mean octal. You can do number base conversions with the format command, where the format is %x for hex, %d for decimal, %o for octal, and the input number should have the C-like markup to indicate its base:

<dl><dd> </dd></dl>

<dl><dd> </dd></dl>

<dl><dd> </dd></dl>

<dl><dd> </dd></dl>

Variables with integer value can be most efficiently modified with the incr command:

The maximal positive integer can be determined from the hexadecimal form, with a 7 in front, followed by several "F" characters. Tcl 8.4 can use "wide integers" of 64 bits, and the maximum integer there is

<dl><dd> </dd></dl>

Demonstration: one more, and it turns into the minimum integer:

<dl><dd> </dd></dl>

Bignums: from Tcl 8.5, integers can be of arbitrary size, so there is no maximum integer anymore. Say, you want a big factorial:

<dl><dd> </dd></dl>

IEEE special floating-point values: Also from 8.5, Tcl supports a few special values for floating-point numbers, namely Inf (infinity) and NaN (Not a Number):

<dl><dd> </dd></dl>

<dl><dd> </dd></dl>

<dl><dd> </dd></dl>

<dl><dd> </dd></dl>

<dl><dd> </dd></dl>

Booleans
Tcl supports booleans as numbers in a similar fashion to C, with 0 being false and any other number being true. It also supports them as the strings "true", "false", "yes" and "no" and few others (see below). The canonical "true" value (as returned by Boolean expressions) is 1.

<dl><dd> </dd></dl>

Characters
Characters are abstractions of writing elements (e.g. letters, digits, punctuation characters, Chinese ideographs, ligatures...). In Tcl since 8.1, characters are internally represented with Unicode, which can be seen as unsigned integers between 0 and 65535 (recent Unicode versions have even crossed that boundary, but the Tcl implementation currently uses a maximum of 16 bits). Any Unicode U+XXXX can be specified as a character constant with an \uXXXX escape. It is recommended to only use ASCII characters (\u0000-\u007f) in Tcl scripts directly, and escape all others.

Convert between numeric Unicode and characters with

Watch out that int values above 65535 produce 'decreasing' characters again, while negative int even produces two bogus characters. format does not warn, so better test before calling it.

Sequences of characters are called strings (see above). There is no special data type for a single character, so a single character is just a string on length 1 (everything is a string). In UTF-8, which is used internally by Tcl, the encoding of a single character may take from one to three bytes of space. To determine the bytelength of a single character:

String routines can be applied to single characters too, e.g [string toupper] etc. Find out whether a character is in a given set (a character string) with

As Unicodes for characters fall in distinct ranges, checking whether a character's code lies within a range allows a more-or-less rough classification of its category:

This is a useful helper to convert all characters beyond the ASCII set to their \u.... escapes (so the resulting string is strict ASCII):

Internal representation
In the main Tcl implementation, which is written in C, each value has both a string representation (UTF-8 encoded) and a structured representation. This is an implementation detail which allows for better performance, but has no semantic impact on the language. Tcl tracks both representations, making sure that if one is changed, the other one is updated to reflect the change the next time it is used. For example, if the string representation of a value is "8", and the value was last used as a number in an [expr] command, the structured representation will be a numeric type like a signed integer or a double-precision floating point number. If the value "one two three" was last used in one of the list commands, the structured representation will be a list structure. There are various other "types" on the C side which may be used as the structured representation. As of Tcl 8.5, only the most recent structured representation of a value is stored, and it is replaced with a different representation when necessary. This "dual-porting" of values helps avoid, repeated parsing or "stringification", which otherwise would happen often because each time a value is encountered in source code, it is interpreted as a string prior to being interpreted in its current context. But to the programmer, the view that "everything is a string" is still maintained.

These values are stored in reference-counted structures termed objects (a term that has many meanings). From the perspective of all code that uses values (as opposed to code implementing a particular representation), they are immutable. In practice, this is implemented using a copy-on-write strategy.

Variables
Variables can be local or global, and scalar or array. Their names can be any string not containing a colon (which is reserved for use in namespace separators) but for the convenience of $-dereference one usually uses names of the pattern [A-Za-z0-9_]+, i.e. one or more letters, digits, or underscores.

Variables need not be declared beforehand. They are created when first assigned a value, if they did not exist before, and can be unset when no longer needed:

Retrieving a variable's value with the $foo notation is only syntactic sugar for [set foo]. The latter is more powerful though, as it can be nested, for deeper dereferencing:

Some people might expect $$$grill to deliver the same result, but it doesn't, because of the Tcl parser. When it encounters the first and second $ sign, it tries to find a variable name (consisting of one or more letters, digits, or underscores) in vain, so these $ signs are left literally as they are. The third $ allows substitution of the variable grill, but no backtracking to the previous $'s takes place. So the evaluation result of $$$grill is $$bar. Nested [set] commands give the user more control.

Local vs. global
A local variable exists only in the procedure where it is defined, and is freed as soon as the procedure finishes. By default, all variables used in a proc are local.

Global variables exist outside of procedures, as long as they are not explicitly unset. They may be needed for long-living data, or implicit communication between different procedures, but in general it's safer and more efficient to use globals as sparingly as possible. Example of a very simple bank with only one account:

This illustrates two ways of referring to global variables - either with the global command, or by qualifying the variable name with the :: prefix. The variable amount is local in both procedures, and its value is that of the first argument to the respective procedure.

Introspection:

To make all global variables visible in a procedure (not recommended):

Scalar vs. array
All of the value types discussed above in Data types can be put into a scalar variable, which is the normal kind.

Arrays are collections of variables, indexed by a key that can be any string, and in fact implemented as hash tables. What other languages call "arrays" (vectors of values indexed by an integer), would in Tcl rather be lists. Some illustrations:

A fanciful array name is "" (the empty string, therefore we might call this the "anonymous array" :) which makes nice reading:

Note that arrays themselves are not values. They can be passed in and out of procedures not as $capital (which would try to retrieve the value), but by reference. The dict type (available from Tcl 8.5) might be better suited for these purposes, while otherwise providing hash table functionality, too.

System variables
At startup, tclsh provides the following global variables:
 * argc : number of arguments on the command line
 * argv : list of the arguments on the command line
 * argv0 : name of the executable or script (first word on command line)
 * auto_index : array with instructions from where to load further commands
 * auto_oldpath : (same as auto_path ?)
 * auto_path : list of paths to search for packages
 * env : array, mirrors the environment variables
 * errorCode : type of the last error, or {}, e.g. ARITH DIVZERO {divide by zero}
 * errorInfo : last error message, or {}
 * tcl_interactive : 1 if interpreter is interactive, else 0
 * tcl_libPath : list of library paths
 * tcl_library : path of the Tcl system library directory
 * tcl_patchLevel : detailed version number, e.g. 8.4.11
 * tcl_platform : array with information on the operating system
 * tcl_rcFileName : name of the initial resource file
 * tcl_version : brief version number, e.g. 8.4

One can use temporary environment variables to control a Tcl script from the command line, at least in Unixoid systems including Cygwin. Example scriptlet:

This script will typically report

<dl><dd> </dd></dl>

To remote-control it without editing, set the DO variable before the call:

which will evidently report

<dl><dd> </dd></dl>

Dereferencing variables
A reference is something that refers, or points, to another something (if you pardon the scientific expression). In C, references are done with *pointers* (memory addresses); in Tcl, references are strings (everything is a string), namely names of variables, which via a hash table can be resolved (dereferenced) to the "other something" they point to:

This can be done more than one time with nested set commands. Compare the following C and Tcl programs, that do the same (trivial) job, and exhibit remarkable similarity:

...and Tcl:

The asterisks in C correspond to calls to  in Tcl dereferencing. There is no corresponding operator to the C  because, in Tcl, special markup is not needed in declaring references. The correspondence is not perfect; there are four  calls and only three asterisks. This is because mentioning a variable in C is an implicit dereference. In this case, the dereference is used to pass its value into printf. Tcl makes all four dereferences explicit (thus, if you only had 3 set calls, you'd see hello, i). A single dereference is used so frequently that it is typically abbreviated with $varname, e.g.

has set where C uses asterisks, and $ for the last (default) dereference.

The hashtable for variable names is either global, for code evaluated in that scope, or local to a proc. You can still "import" references to variables in scopes that are "higher" in the call stack, with the upvar and global commands. (The latter being automatic in C if the names are unique. If there are identical names in C, the innermost scope wins).

Variable traces
One special feature of Tcl is that you can associate traces with variables (scalars, arrays, or array elements) that are evaluated optionally when the variable is read, written to, or unset.

Debugging is one obvious use for that. But there are more possibilities. For instance, you can introduce constants where any attempt to change their value raises an error:

<dl><dd> </dd></dl>

The trace callback gets three words appended: the name of the variable; the array key (if the variable is an array, else ""), and the mode:

 * r - read
 * w - write
 * u - unset

If the trace is just a single command like above, and you don't want to handle these three, use a comment ";#" to shield them off.

Another possibility is tying local objects (or procs) with a variable - if the variable is unset, the object/proc is destroyed/renamed away.

title: Tcl Programming/Introduction


text:
Cookbook:Semolina Burger

| Vegan cuisine

Ingredients

 * Semolina
 * Oat flakes
 * Onions
 * Maize (optional)
 * Paprika (optional)
 * Breadcrumbs
 * Salt
 * Pepper
 * Cumin (optional)
 * Oregano (optional)
 * Savory (optional)

Procedure

 * 1) Mix semolina with oat flakes at a weight ratio of 4:1.
 * 2) Add water and stir until you get a viscous dough.
 * 3) Cut onions into pieces and fry them with some oil. Add maize and paprika to taste when the onions turn glassy. Mix into the dough.
 * 4) Shape the dough into patties.
 * 5) Combine breadcrumbs, salt, pepper, cumin, oregano, and savory to make the breading mixture.
 * 6) Spread the breading mixture on a plate. Press the patties into the breading, coating them on both sides. Shake off excess breading.
 * 7) Fry the patties in a hot, oiled pan, flattening them with a spatula to sear well. If you use too much oil the patties will be soaked in fat; if you use too little the breading mix will not be fried. It's probably best to add a little bit of oil and then shuffle the patties around in the pan. The patties very quickly become robust enough so you can easily pick them up and turn them with a spatula to see if the other side had enough oil.

Notes, tips, and variations

 * Adding 5–10% cornstarch by weight makes the patties looser.
 * You can mix semolina and oat flakes 1:1, which makes the patties more compact.
 * Adding gluten (or seitan mix) makes the patties tougher, without making them more compact.
 * Without breading, the patties require less oil.
 * You can add spices to the patty dough, but most spices should go into the breading mix.

title: Cookbook:Semolina Burger


text:
Tcl Programming/Appendix

Resources

 * The main page of Tcl developers is the Tcl Developer Xchange.
 * Download a free binary ActiveTcl distribution at ActiveState.
 * The main USENET forum dedicated to this language is news:comp.lang.tcl.
 * In German, there's also http://www.self-tcl.de/forum for questions and answers
 * The main user wiki is The Tclers Wiki.
 * The Tclers' Chat can provide quick response to questions: Jabber all.tclers.tk:5222, IRC freenode #tcl, or Webchat http://mini.net/cgi-bin/chat.cgi (all of the three being relayed between each other)
 * The Tcl man pages can be found here.
 * The Tk man pages can be found here.
 * Documentation on Tcllib, the Tcl standard library is here.
 * There is a tutorial for Tcl here.

For Web development, there are:
 * pure-Tcl Web servers like Tclhttpd, which can be embedded in your Tcl-enabled applications to provide Web-based interfaces,
 * Tcl-based Web servers like AOLServer, which are much faster than their pure-Tcl cousins and able to support a heavy load, and
 * Tcl Web server modules (see Apache Tcl for examples) that enable Tcl Web applications with bog-standard Web servers.

ActiveState Community License
''This is the license of the "Batteries-included" ActiveTcl distribution. Note that you cannot redistribute ActiveTcl "outside your organization" without written permission.'' The part between "AGREEMENT" and "Definitions:" is the more free, BSD-style license of Tcl and Tk itself.

Preamble:

The intent of this document is to state the conditions under which the Package (ActiveTcl) may be copied and distributed, such that ActiveState maintains control over the development and distribution of the Package, while allowing the users of the Package to use the Package in a variety of ways.

The Package may contain software covered by other licenses:

TCL LICENSE AGREEMENT

This software is copyrighted by the Regents of the University of California, Sun Microsystems, Inc., Scriptics Corporation, and other parties. The following terms apply to all files associated with the software unless explicitly disclaimed in individual files. The authors hereby grant permission to use, copy, modify, distribute, and license this software and its documentation for any purpose, provided that existing copyright notices are retained in all copies and that this notice is included verbatim in any distributions. No written agreement, license, or royalty fee is required for any of the authorized uses. Modifications to this software may be copyrighted by their authors and need not follow the licensing terms described here, provided that the new terms are clearly indicated on the first page of each file where they apply. IN NO EVENT SHALL THE AUTHORS OR DISTRIBUTORS BE LIABLE TO ANY PARTY FOR DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OF THIS SOFTWARE, ITS DOCUMENTATION, OR ANY DERIVATIVES THEREOF, EVEN IF THE AUTHORS HAVE BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. THE AUTHORS AND DISTRIBUTORS SPECIFICALLY DISCLAIM ANY WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, AND NON-INFRINGEMENT. THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, AND THE AUTHORS AND DISTRIBUTORS HAVE NO OBLIGATION TO PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS. GOVERNMENT USE: If you are acquiring this software on behalf of the U.S. government, the Government shall have only "Restricted Rights" in the software and related documentation as defined in the Federal Acquisition Regulations (FARs) in Clause 52.227.19 (c) (2). If you are acquiring the software on behalf of the Department of Defense, the software shall be classified as "Commercial Computer Software" and the Government shall have only "Restricted Rights" as defined in Clause 252.227-7013 (c) (1) of DFARs. Notwithstanding the foregoing, the authors grant the U.S. Government and others acting in its behalf permission to use and distribute the software in accordance with the terms specified in this license.

Definitions:

"ActiveState" refers to ActiveState Corp., the Copyright Holder of the Package.

"Package" refers to those files, including, but not limited to, source code, binary executables, images, and scripts, which are distributed by the Copyright Holder.

"You" is you, if you are thinking about copying or distributing this Package.

Terms:

1. You may use this Package for commercial or non-commercial purposes without charge.

2. You may make and give away verbatim copies of this Package for personal use, or for use within your organization, provided that you duplicate all of the original copyright notices and associated disclaimers. You may not distribute copies of this Package, or copies of packages derived from this Package, to others outside your organization without specific prior written permission from ActiveState (although you are encouraged to direct them to sources from which they may obtain it for themselves).

3. You may apply bug fixes, portability fixes, and other modifications derived from ActiveState. A Package modified in such a way shall still be covered by the terms of this license.

4. ActiveState's name and trademarks may not be used to endorse or promote packages derived from this Package without specific prior written permission from ActiveState.

5. THIS PACKAGE IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.

ActiveState Community License Copyright (C) 2001-2003 ActiveState Corp. All rights reserved.

title: Tcl Programming/Appendix


text:
Wikijunior:Big Cats/Margay

Margays are the masters of vertical space, spending much of their lives in the branches of trees where they pursue their prey and even nap hanging upside down by their back feet.

Where do margays live?
Margays live from Mexico in the north all the way south to northern Argentina. Margays also live in rainforests. Margays used to be found in Texas, but have been hunted out all the way to southern Mexico. They prefer to live in damp areas.

What do margays look like?
A margay has spots like a cheetah, two stripes on its forehead, and some on its cheeks. It also has thick stripes on its tail. Like a tiger's, leopard's, or cheetah's, the margay's patterns are specific to each individual. It has very large eyes and a very long tail that is 70 percent as long as its body. It can jump higher than an ocelot by 20 feet! The margay, also known as the Long Tailed Spotted Cat, is similar in appearance to the ocelot —- its body however, is smaller, growing up to 27 inches. In comparison with the ocelot, the margay displays longer legs and tail. This cat is often confused with its relatives –- the ocelot and the oncilla. Their coats are very similar. The margay's fur is thick and its tail is really long. The tail is used as weight to help with balance. The margay is a spotted, golden brown cat with white on the belly, chest, throat, and chin. The spots may be solid black or have pale centers. The ears have white eye spots on the backs and the tail is either ringed or spotted. Margays weigh between 9-20 pounds and are between 34-52 inches long. The margay also has extremely big eyes, which helps its night time vision. Also the Margay is one of two species of cat that have flexible enough ankle joints to be able to climb down trees headfirst like a squirrel!

What do margays eat, and how do they catch their prey?
Margays are agile hunters, leaping after and chasing birds and monkeys through the treetops. The ankles on their back legs are so flexible that they can run down a tree head first like a squirrel. Since Margays are such great tree climbers, they often eat other mammals that live in trees such as big eared climbing rats, squirrels, opossums, small monkeys, and sloths. They also eat tree frogs, lizards and birds. They also will sometimes eat insects, grasses and sometimes even fruit. Margays can hunt in the dark due to their huge eyes, which can see exceptionally well in the dark.

Fun facts
See how much you know about margays:
 * Margays have the ankle flexibility needed to climb down trees head first.
 * Margays can hang from a branch by one back foot.
 * Captive margays have lived for 20 years.
 * Margay kittens weigh about 450 grams at birth (In comparison, a domestic kitten may weigh 110 grams).
 * Margays scientific name is Leopardus Wiedii

For more information
Next Topic: Jaguarundis Wikijunior Großkatzen/ Langschwanzkatze
 * Wikipedia: Margay

title: Wikijunior:Big Cats/Margay


text:
Wikijunior:Big Cats/Jaguarundi

Jaguarundis are one of the oddest members of the cat family, rarely seen, and often thought to be otters when they were spotted. Their scientific name, Herpailurus, means "snake-like cat".

Where do jaguarundis live?
Jaguarundis live in Central and South America, and in the southern tip of Texas. They live in areas of lowland brush close to a running water source and will occasionally inhabit dense tropical areas.

What do jaguarundis look like?
This medium-sized cat has an average length of 65 cm (30 inches) with 45 cm (20 inches) of tail. It has short legs and an appearance somewhat like an otter; the ears are short and rounded. The fur is a uniform chestnut brown, but can range from grey to dark brown. Their coats have no markings except for spots at birth.

What do jaguarundis eat, and how do they catch their prey?
Jaguarundis eat fish, small mammals, reptiles and birds. They feel comfortable in trees but prefer to hunt on the ground. They can also eat rabbits, armadillos, small rodents, lizards, and bird eggs. They can enter the water or scale a tree to reach their prey.

Fun facts
See how much you know about the jaguarundi:
 * They have a name like the jaguars, but are the closest living relative of the puma.
 * The Jaguarundi can reach speeds of over 60 mph
 * They are diurnal, unlike most cats, they are active during the day.
 * They have retractable claws
 * They have rough bumps on their tongue; Papillae, that help them scrape meat from the bone.
 * They sleep in enclosed spaces, such as hollow logs or caves.

For more information

 * Wikipedia: Jaguarundi

Next Topic: Rusty-spotted cats

Wikijunior Großkatzen/ Jaguarundi

title: Wikijunior:Big Cats/Jaguarundi