Tcl

Appeared in:
1988
Influenced by:
Paradigm:
Typing discipline:
File extensions:
.tcl
Versions and implementations (Collapse all | Expand all):
Programming language

Tcl (abbreviation for “Tool Command Language”) is a scripting language. It is used for rapid prototyping, writing automated testing harnesses and scripting applications.

Tcl was created by John Ousterhout in 1988. The intention was to create a simple interpreted language that would provide a set of basic programming facilities, would be extensible and could be easily integrated and reused in many tools.

Around 1990 Tcl got accompanied by Tk — a GUI toolkit that allowed to develop graphical user interfaces for Unix. The combination of Tcl’s embeddability and Tk’s ease of use led to rapid growth of language popularity.

Main features of Tcl:

  • programs are compiled to bytecode and then interpreted.
  • all elements of the program, including things like loops and function definitions, are commands.
  • commands are written in prefix notation, i.e., command name is first and arguments follow.
  • most commands are variadic, i.e., can take varying number of arguments.
  • all commands generate error messages when used improperly.
  • the language provides multiple data types; however, all data and source code can be manipulated as strings.
  • all values are immutable: whenever they need to be changed, they are just replaced with newly created values.
  • Tcl didn’t provide support for object-oriented programming until version 8.6; but OOP could be used via extension packages.

Tcl expressions are written either in curly braces (to suppress all substitutions within them) or as-is or in double braces, in which case three types of substitution are used:

  • command substitution replaces the contents of squared brackets with the result of its evaluation, for example, [expr 1+2] will be replaced with 3.
  • variable substitution replaces the name of a variable preceded by $ sign with its contents.
  • backslash substitution is similar to other languages: a backslash followed by a character is replaced with another character.

Elements of syntax:

Inline comments #
Variable declaration with assignment set <varname> <value>
Block { ... }
Comparison < > <= >=
Function definition proc <name> <args> <body>
Function call <name>(<args>) or <name> <args>
Function call with no parameters <name>
Sequence ; OR newline
If - then if {condition} { ... }
If - then - else if {condition} { ... } elseif {condition} { ... } else { ... }
While condition do while (condition) ...
For each value in a numeric range, 1 increment for {set i 0} {$i <= 10} {incr i} { ... }

Tcl logo
Tcl logo

Examples:

Fibonacci numbers:

Example for versions ActiveTcl 8.5, Tcl 8.5.7

This example uses iterative definition of Fibonacci numbers. lassign assigns successive elements from the list passed as first argument (created by [list ...]) to the variables given by the next arguments (fib1 and fib2 in this case). This command was moved to language core in Tcl 8.5; before that it was part of TclX package.

set fib1 0
set fib2 1
set s ""
for {set i 0} {$i < 16} {incr i} {
    lassign [list $fib2 [incr fib2 $fib1]] fib1 fib2
    append s "$fib1, "
}
puts "$s..."

Fibonacci numbers:

Example for versions ActiveTcl 8.5, Tcl 8.5.7

This example uses recursive definition of Fibonacci numbers. Function fib is defined in namespace tcl::mathfunc, so that it can be used as math function in expr expressions.

proc tcl::mathfunc::fib {n} {
    if {$n<=1} {
        return 1
    } else {
        return [expr fib([expr {$n - 1}]) + fib([expr {$n - 2}])]
    }
}

set s ""
for {set i 0} {$i < 16} {incr i} {
    append s [expr fib($i)] ", "
}
puts "$s..."

Hello, World!:

Example for versions ActiveTcl 8.5, JTcl 2.1.0, Tcl 8.4, Tcl 8.5.7
puts "Hello, World!"

Factorial:

Example for versions ActiveTcl 8.5, JTcl 2.1.0, Tcl 8.4, Tcl 8.5.7

This example uses iterative factorial definition. In Tcl 8.4 values of factorials starting with 13! are calculated incorrectly due to overflow. In later versions and other implementations all values are correct.

set fact 1
for {set i 0} {$i <= 16} {incr i} {
    puts "$i! = $fact"
    set fact [expr {$fact * ($i + 1)}]
}

Quadratic equation:

Example for versions ActiveTcl 8.5, JTcl 2.1.0, Tcl 8.4, Tcl 8.5.7
set A [gets stdin]
if {$A==0} { 
    puts "Not a quadratic equation."; 
    return 
}
set B [gets stdin]
set C [gets stdin]
set D [expr {$B*$B-4*$A*$C}]
set r [expr {-0.5*$B/$A}]
set i [expr {0.5*sqrt(abs($D))/$A}]
if {$D==0} {
    puts "x = $r"
} elseif {$D>0} {
    puts "x1 = [expr {$r+$i}]"
    puts "x2 = [expr {$r-$i}]"
} else {
    puts "x1 = ($r, $i)"
    puts "x2 = ($r, [expr {-$i}])"
}

CamelCase:

Example for versions ActiveTcl 8.5, JTcl 2.1.0, Tcl 8.4, Tcl 8.5.7

This example shows character-wise string processing. A regular expression is used to check whether current character is a letter.

set S [gets stdin]
set S [string tolower $S]
set L [string length $S]
set lastSpace 1
set cc ""
for {set i 0} {$i < $L} {incr i} {
    set letter [string index $S $i]
    if { [string match {[a-z]} $letter] } {
        if { $lastSpace == 1 } { set letter [string toupper $letter] }
        append cc $letter
        set lastSpace 0
    } else {
        set lastSpace 1
    }
}
puts $cc

Fibonacci numbers:

Example for versions ActiveTcl 8.5, JTcl 2.1.0, Tcl 8.4, Tcl 8.5.7

This example uses iterative definition of Fibonacci numbers.

set fib1 0
set fib2 1
set s ""
for {set i 0} {$i < 16} {incr i} {
    set fib3 [expr {$fib1 + $fib2}]
    set fib1 $fib2
    set fib2 $fib3
    append s "$fib1, "
}
puts "$s..."

Fibonacci numbers:

Example for versions ActiveTcl 8.5, JTcl 2.1.0, Tcl 8.4, Tcl 8.5.7

This example uses tail recursion to calculate the numbers. eval command allows to evaluate the result of calling fib with given arguments without declaring fib as part of any namespace.

proc fib {f1 f2 n} {
    if {$n==0} {
        return $f1
    } else {
        return [eval fib $f2 [expr {$f1 + $f2}] [expr {$n - 1}]]
    }
}

set s ""
for {set i 0} {$i < 16} {incr i} {
    append s [eval fib 1 1 $i] ", "
}
puts "$s..."