Tcl cheat sheet

New in Tcl? Coming from another language? Read on.

This could be fun. I learned almost all of my programming with PHP, and a little bit of Perl. This sheet [L1 ] helped me an awful lot when I tried to learn Perl, so a Tcl cheat sheet may be awfully useful to someone else. Feel free to add other languages.

How about we get the Tcl stuff correct before adding other languages? Roy Terry, 17Jan2003

The following items seem to be referring specifically to use of the languages within a CGI context, rather than as individual characteristics of the languages themselves.


How do you name files:

PHP: file.php3

Perl: file.cgi

Tcl: file.tcl

[Well, technically, the above isn't right, at least for Tcl and Perl. Neither Tcl nor Perl require you to use the ".???" extensions on the files. Some (many? most?) web servers might require one to have an extension on an executable. But even then, one can call Tcl cgi scripts file.tcl without a problem - Tcl wouldn't even care if you called the file "file.php3"...


How do you provide a CGI script to the server:

PHP: scripts embedded within <?php..?> tags on the HTML page itself.

Perl: whole file is script

Tcl: whole file is script (unless you use mod_dtcl in Apache 1.3.x or mod_tcl/rivet in Apache 2.x (or likely some other options; there everything is like PHP)


How do you produce output for the user

PHP: can mix raw HTML and PHP

Perl: the cgi script must print all output, whether HTML or plain text

Tcl: must print all output (unless you use mod_dtcl in Apache 1.3.x or mod_tcl/rivet in Apache 2.x, there everything is like PHP)


Is there any specific magic needed when writing the specific page/script?

PHP: no requirements for first line inside the embedding tags

Perl: first line is #!/usr/local/bin/perl or any other path to your Perl interpreter (but is that a requirement?)

Tcl: first line can be #!/usr/local/bin/tclsh or any other path to your Tcl interpreter (but that is absolutely irrelevant if you are using Windows). See exec magic for the recommended way to start a Tcl file if you want it to behave like an app on *nix systems.

The first line magic is only not required if one is on Windows systems. Otherwise, it is required if one wants the script file mentioned to automatically execute with the language interpreter. If the user is willing to supply the interpreter along with the script name (aka perl something or tclsh tkconsole, etc.), then the script does not require the first magic line.


What type of permissions does the code need?

PHP: since the code is not an independant executable file, but just tags within an HTML page, no extra permissions are needed

Perl: On systems which have such concepts, to run the code, you must make the code an executable file

Tcl: On systems which have such concepts, to run the code, you must make the code an executable file


How do you make the code active?

PHP: chmod 644 file.php3 (set script file's permission so it is readable)

Perl: chmod a+x file.cgi (set script file's permission so it is executable)

Tcl: chmod a+x file.tcl (set script file's permission so it is executable)


How do you produce output in the language?

PHP: echo "stuff\n";

Perl: print "stuff\n"; OR

             printf "I am using %s printing conventions!", 'C';

Tcl: puts stuff OR

            puts "some stuff" 

OR

            set other {some string of information}
            puts "some $other stuff" 

OR

            puts {some stuff}

OR

            puts [format "I am using %s printing conventions!" C]

It may be useful here to point out that Tcl adds a trailing newline by default. To disable this behaviour use the -nonewline option to puts.

puts -nonewline "some stuff"

Also, note that there is no comma between arguments in Tcl, whereas in Perl, there are. Also, while Tcl permits a trailing semicolon (;), it is only required when used as a statement seperator.


What is the format for using variables?

PHP: All variables $var

Perl: $var is a scalar variable; @var is an array variable, %var is a hash variable.

Tcl: var refers to the name of a variable which is needed every time you want to modify its contents (write to the variable); or $var refers to the content of the variable to be used when you want to read the variable . See set for more details. var(index) refers to an array variable.


If variable types are supported, how does one reference the differing types?

PHP: $var always means one thing

Perl: $var, @var, %var, var are different variable types (string, array, hash)!

Tcl: since all variables var have a $ in front, $var always means the same thing. But beware: var could be a scalar or an array variable and has to be used according to that!


What kind of collection data type does the language support?

PHP: $var = array(1,2,3);

Perl: @var = (1,2,3); or %var = ("apple"=>'value for apple', "potato"=>'val2', "carrot"=>'carrot is red');

Tcl: well, there are lists which work very fine, plus there are arrays (which are called hashes in some other languages), see below

 set var "1 2 3"  '''OR'''  set var [ list 1 2 3 ] 

While the latter is preferred especially in cases where the contents are not as simple as "1 2 3", but may contain spaces, return values from functions and so on. Only the list command helps you to correctly use quoting.

and arrays...

 array set var "key1 value1 key2 value2 key3 value3"

PHP: "numeric" arrays and "associative" arrays

Perl: "arrays" and "hashes"

Tcl: "lists" and associative "arrays" - of course the associative arrays can have numbers as indexes.

(NEM and we now have dicts)


How do you reference a specific member of a data collection type?

PHP: $var[1] is second element of array $var

Perl: $var[1] is second element of array @var; $var{1} is the data for key value 1 for hash %var

Tcl: [ lindex $var 1 ] is the second element of list $var and $var(1) is the data for array key value 1. [dict get $var 1] returns the value associated with 1 in the dict $var.


How do you determine the size of a collection data type?

PHP: count($var) is number of elements in array $var

Perl: scalar(@var) is number of elements in array @var; scalar(keys %var) is the number of elements in the hash %var

Tcl: [ llength $var ] is length of list, and [array size var] is number of elements in array. [dict size $var] is the number of mappings in a dictionary.


How do you display all the elements of the collection data type?

PHP: for ($i=0; $i<count($var); $i++) echo $var[$i];

Perl: foreach $thing (@var) { print $thing; }; or just print @var; for hashes: print map {"$_->$var{$_},"} keys %var;

Tcl: for { set i 0 } {$i < [ llength $var ] } { incr i } { puts [ lindex $var $i ] }

NEM This Tcl example would be far better written as: foreach thing $var { puts $thing }

RT And this is better yet: join $var, or [join $var <br>], etc.

Working through an array works like this:

 foreach index [array names var] {
    puts $var($index)
 } ;# foreach

Note however that the Tcl foreach has at least one differing characteristic from Perl's foreach.

In perl, one has to note this behavior -- the index variable of a Perl foreach loop is a reference to the elements of the array, NOT a copy of the element!

 @x = (1, 2, 3);                # Create a 3 element list/array
 foreach $i (@x) {
        print $i++ . "\n";
 }
 # At this point, array contains 2, 3, 4!

In Tcl, using a similar program structure

 set x [list 1 2 3]
 foreach i $x {
        puts "$i"
        incr i
 }

At the end of the loop, the x list members have not changed their values. Certainly one can construct code that will update it. This note is just to let someone trying to convert code from one language to another be aware of a difference in the behavior.

For dictionaries, you can just print the dictionary. :^) However, that's not always the neatest way of doing it. Here's a neater way:

 dict for {key val} $theDictVar {
    puts "$key => $val"
 }

As with arrays, modifying key or val in the body of the [dict for] won't affect the dictionary. In fact, you can even update the dictionary in the variable while the [dict for] is progressing and the loop will not be affected at all.


How do you create a string from an array ?

[Huh? Why would you _want_ to do this? Please be a bit more specific about what it is that you are trying to accomplish, so that comperable functionality can be coded. ]

PHP: join(":",array(1,2,3))

Perl: join ":", 1,2,3; # I don't know PHP, but suspect that before the semicolon here, you need to add a , "\n" to produce a newline.

Tcl: join [ list 1 2 3 ] : (yeah, yeah, you can wrap the colon in quotes if you're queasy)

[Um? A list isn't an array. First convert array to list with array get e.g.:

 join [[ array get env ]] :

Also note that parray prints a formatted output of "array(xx) = value" e.g.:

 parray env

]

However, neither of these results in the same output as the first two. The PHP and Perl statements create an array containing the values 1, 2, and 3, then retrieve the values of the array, and outputs those values separated by a colon. The Tcl array and dict need another round of examples to get something a bit closer to the effort.

As for the question of why one would want to do this - why, to produce a csv type record of the values in the array, perhaps?


How are the collection data types treated as objects?

Er... what is a "type"? ;-) If you like objects you could use incr Tcl or stooop [Again, please be a bit more specific about _what_ it is you are going for here so that comparable information can be supplied.]

PHP: associative arrays are arrays

Perl: associative arrays are their own type

Tcl: Lists and dicts are values. Arrays are collections of variables. The array get and array set commands make a value out of the data in an array and vice versa.

TJK - The Snit package (found in tcllib) is a pure-tcl object framework that uses type definition as its model. If you need "types" that look like objects then use Snit.


How do you create an array?

PHP: $var = array(1=>"ho","hi"=>4);

Perl: %var = (1=>"ho","hi"=>4);

Tcl: array set var [list 1 ho hi 4] or alternatively: set var(1) ho; set var(hi) 4 No explicit creation is necessary.


Access value of single array element 'ho'

PHP: $var['ho']

TJK or $var[ho] (if constant with no white space)

Perl: $var{ho} (if var is a hash (%var) - if var is an array (@var) then its existence does not influence %var; for constants with no white space, quotes not needed)

Tcl: $var(ho) (for constants with no white space, quotes not needed)


How do you iterate through a hash?

PHP: foreach ($var as $k => $v) {...}

TJK or foreach( array_keys($var) as $key ) {...}

Perl: while (($k,$v) = each %var) {...}

Tcl: foreach { key value } [ array get var ] {...} OR

              set srchId [array startsearch var];set srchId [array nextelement var $srchId]; array donesearch var $srchId

Copying the contents of an array A to an array B would in Tcl be

  array set B [array get A]

if that is what was intended.


to be continued...

Roy Terry, 17Jan2003 - say this looks helpful. On your next pass can you be more specific on 1) What each section is trying to demonstrate, and 2) your questions about Tcl. "??? - confusing" doesn't give folks a good idea of what additional info you need. One obvious correction: Tcl uses parens, not square brackets, to index arrays. Further more the single quote has absolutely no special meaning in Tcl, it does not quote things and it will not be removed by the parser; so best to avoid it. Now I see something else: In Tcl variables can be either an array or a string value and that's determined by usage.

LES: It's not Tcl that confuses me. It's the PHP and Perl examples that confused me, so I am not sure how to translate them into Tcl. For example: instead of saying $var['ho'] is element indexed by 'ho' , I'd rather say "ho" is element indexed by $var['1']. Do I make myself clear? RT - no I don't think you do. Take a look at the array access segment now. I think it helps to put the "operation" at the top of the section and then just list the code sample.

VK: I fixed many Perl samples: there was an error in one place and misunderstanding in another: in Perl you can have $var @var %var - those are 3 different concepts - a scalar, an array and hash. It is wrong to think that once 'var' is a hash, you can't use it as an array.

glennj (updated some items above)