Tcl and Unicon: a Tale of Two VHLL's

Evolution of VHLL and "Scripting" Language Categories

Today's talk describes two very high level languages, Tcl and Unicon. The first very high level language (Lisp) followed close on the heels of FORTRAN in the earliest days of of computer science. In those days, an interactive interpreter with dynamic typing and a garbage collector were ultra revolutionary.

In 1994 a USENIX Symposium on VHLL's brought together many (not all) of the major language developers. Since this conference included many languages, especially the Lisp and Scheme camps, it did not focus enough attention on the stars of the day, Perl and Tcl, to satisfy them. They wanted a higher market share of attention, and especially didn't want to hear that they hadn't invented the language category and in fact had ignored many language features done better in earlier very high level languages, and had repeated mistakes these earlier languages had encountered and had to overcome over a 30 year timespan.

So, they stopped having VHLL Symposia, focused on single-language conferences on Tcl and Perl where they wouldn't have to hear that they might learn a thing or two from other programming language designers, and shortly thereafter the inventor of Tcl, John Ousterhout, who is a brilliant marketer and certifiable genius, founded a company to develop Tcl and wrote a paper ignoring the other very high level languages and extolling Scripting Languages as the category to watch, partly as part of his company's marketing campaign.

Both languages discussed below are to be contrasted with Systems Programming Languages, which are languages designed for writing all types of software systems in an imperative style that maps 1:1 onto underlying hardware. C, C++, Modula-2, Ada, and Java are all fine systems programming languages.

  • This lecture is necessarily heavily biased; in order to slightly reduce the high level of bias, I take my examples from the Tcl book [Ousterhout94] and Tcl articles.


    What is Tcl? What is Unicon?
  • A free language hosted at Sourceforge; sf.net/projects/tcl
  • Main site is www.tcl.tk, the Tcl Developer Xchange
  • A free language hosted at SourceForge; sf.net/projects/unicon
  • Main site is unicon.sf.net
  • A Scripting Language
    a language designed mainly for orchestrating/glueing/coordinating functionality provided by external programs or components. The "script" is usually interpreted, and is not where the interesting or hard parts of the functionality are implemented".
  • An Applications Language
    a language designed for end-user applications programmers, with algorithms, data structures, and IO capabilities appropriate for expressing software designs. Semantic level corresponds more to UML than to the machine. Syntax designed for expressive power and human readability, not simplicity of intepretation as in the case of Lisp and Tcl.
  • Designed to be an embeddable interpreter, mixed with C.
  • "Speed doesn't matter when you're glue"
  • Claim to fame: Tk, an interpretive X11 widget set
  • A rapid prototyping language, designed to stand alone
  • "Speed matters: programming speed, then runtime speed"
  • Special strengths: text processing, complex algorithms & data structures.


  • Tcl Background Unicon Background
  • Author a Berkeley ECE professor, first language effort
  • Authors are computer scientists who studied programming languages.
  • Invented starting around 1987
  • Invented starting around 2000, or 1980
  • Based mainly on UNIX shell scripting
  • Based on Icon (U Arizona) and SNOBOL (AT&T)
  • Funded by Sun, Scriptics (now defunct)
  • Spectacularly successful; tens of thousands; has outgrown its niche
  • commercial Tcl available @ $500/year from Sophos
  • Funded by NSF, NLM
  • Slow growth; hundreds of users; has no niche
  • GPL; no plans to commercialize


  • Tcl Basics Unicon Basics
  • Very simple syntax based on 'words' + devilish mix of {}, []
  • "Everything is a string" mentality; lists are strings, etc.
  • Implicit string catenation; source text means itself
  • Algol-like syntax similar to C/Pascal
  • "Everything is an expression"; rich dynamic type system
  • Implicit expression evaluation; source code is evaluated

  • Tcl hello world
  • Unicon hello world
  • #!/usr/bin/wish -f
    button .b -text "Hello world" -command exit
    pack .b
    
    procedure main()
       write("hello, world")
    end
    

  • Tcl expression and assignment
  • Unicon expression and assignment
  • set a 122
    set 122 a
    expr 24/3.2
    eval {set a 122} # a True interpreter
    set y x+10
    set b [expr $a*4]
    incr x 12
    
    a := 122
    122 := a # would cause a runtime error
    24/3.2
    # no "eval" in Unicon
    y := "x+10"
    b := a*4
    x +:= 12
    

  • Tcl strings and structures
  • Unicon strings and structures
  • set msg {Eggs: $2.18/dozen}
    set msg "Eggs: \$$x/dozen"
    set b 101    ;# line comment
    set L {red green blue purple}; lindex $L 2
    concat {a b c} {d e} f {g h i}
    list {a b c} {d e} f {g h i}
    llength {{a b c} {d e} f {g h i}}
    linsert $L 2 X Y Z
    string length abracadabra
    {$s == "New York"}
    set earnings(January) 87966
    set earnings(February) 95400
    set cell $matrix($i,$j) ;# index spaces significant!
    
    msg := "Eggs: $2.18/dozen"
    msg := "Eggs: $" || x || "/dozen"
    b := 101    # line comment
    L := ["red", "green", "blue", "purple"]; L[2]
    [a, b, c] ||| [d, e] ||| [f] ||| [g, h, i]
    [[a, b, c], [d, e], f, [g, h, i]]
    *[[a, b, c], [d, e], f, [g, h, i]]
    insert(L, 3, [ X Y Z ])
    *"abracadabra"
    s == "New York"
    earnings := table(); earnings["January"] := 87966
    earnings["February"] := 95400
    cell := matrix[i,j]
    

  • Tcl logic and control structures
  • Unicon logic and control structures
  • ($x > 4) && ($x < 10)
    button .b -text Hello -fg red
    if {$x<2} {set x 2}
    for {set i 1} {$i <= 10} {incr i} {puts [format "%8d" $i]}
    foreach i {1 2 3 4 5} {
       append msg "$i squared is [expr $i*$i]\n"
    }
    
    4 < x < 10
    b := TextButton("label=Hello", "fg=red")
    if x<2 then x := 2	-or-      x <:= 2
    every i := 1 to 10 do { write(sprintf("%8d", i)) }
    every i := ![1, 2, 3, 4, 5] do {
       msg ||:= i || " squared is " || i*i || "\n"
    }
    

  • Tcl declarations and scoping
  • Unicon declarations and scoping
  • global x y ;# inside EACH procedure
    proc inc {value {increment 1}} { ... }
    proc sum args { ... }
    
    global x, y # once outside all procedures, visible everywhere
    procedure inc(value, increment:1);  ... end
    procedure sum (args[]);  ... end
    

  • Tcl procedures
  • Unicon procedures
  • proc power {base p} {
        set result 1
        while {$p>0} {
            set result [expr $result*$base]
            set p [expr $p-1]
        }
        return $result
    }
    
    procedure power(base, p)
       result := 1
       while p>0 do {
          result *:= base
          p -:= 1
          }
       return result
    end
    
    - or -
    procedure power(base, p)
       result := 1
       every 1 to p do result *:= base
       return result
    end
    
    - or -
    
    base ^ p
    


    Tcl patterns Unicon scanning
  • globbing and regular expressions form sublanguages
  • very concise for simple-to-medium patterns
  • string scanning integrated into expression evaluation
  • more general-purpose, e.g. non-regular languages OK
  • set new {}
    foreach el $L {
       if [string match Tcl*baz $el] {
       lappend new $el
       }
    }
    regexp {^((0x)?[0-9a-fA-F]+|[0-9]+)$} $x
    
    new := ""
    every el := !L do {
       if el ? (="Tcl" & tab(-3) & ="baz") then
          new ||:= el
    }
    hex := &digits ++ 'abcdefABCDEF'
    x ? (((="0x"|"") & tab(many(hex))) | tab(many(&digits))) & pos(0))
    


    Tcl File Handling Unicon File Handling
    #!/usr/bin/tclsh
    if {$argc != 2} {
        error "Usage: tgrep pattern filename"
    }
    set f [open [lindex $argv 1] r]
    set pat [lindex $argv 0]
    while {[gets $f line] >= 0} {
        if [regexp $pat $line] {
            puts $line
        }
    }
    
    link regexp
    procedure main(argv)
       if *argv ~= 2 then
          stop("Usage: tgrep pattern filename")
       f := open(argv[2])
       pat := argv[1]
       while line := read(f) do {
          if ReFind(pat, line) then
             write(line)
          }
    end
    


    Tk Ivib
    entry .base -width 6  -relief sunken -textvariable base
    label .label1 -text "to the power"
    entry .power -width 6 -relief sunken -textvariable power
    label .label2 -text "is"
    label .result -textvariable result
    pack .base .label1 .power .label2 .result -side left \
       -padx 1m -pady 2m
    bind .base  {set result [power $base $power]}
    bind .power  {set result [power $base $power]}
    

    [incr Tcl] Unicon classes
    package require Itcl
    namespace import itcl::*
    class Point {
      public variable x
      public variable y
      constructor {_x _y} {
        set x $_x
        set y $_y
      }
      destructor {}
      public method move {dx dy} {
        set x [expr {$x + $dx}]
        set y [expr {$y + $dy}]
        return [list $x $y]
      }
    }
    
    class Point (x, y)
      method move(dx, dy)
        x +:= dx
        y +:= dy
        return [x, y]
      end
    end
    

    Tcl I don't know how to write in Unicon Unicon I don't know how to write in Tcl
  • upvar # (in Unicon, scalars cannot be by reference)
  • exceptions (Unicon is "failure oriented" instead)
  • break break, break next, etc.
  • static # in Tcl, mangle globals
  • generators; suspend, resume, etc.

  • Tcl stuff that is beyond compare Unicon stuff that is beyond compare
  • Tk, for GUI programming
  • Writing Tcl Applications in C
  • generators and goal-directed evaluation
  • Unicon's 2D and 3D graphics programming

  • Tcl Approximate Speed (Waclena) Unicon Approximate Speed (Waclena)
  • Takeuchi: 520x C
  • fgrep: 42x C
  • invert: 1.7 U
  • Takeuchi: 4.2-23x C
  • fgrep: 8.5-13.2 C
  • invert: 1.0 U
  • Interesting Related Work

  • Keith Waclena's Language Comparisons and Benchmarks
  • Lutz Prechelt's "An Empirical Comparison of C, C++, Java, Perl, Python, Rexx, and Tcl", IEEE Computer, 33:10, 23-29, 2000.