Saturday, 24 October 2020

Why I'm Tcl-ish

I'm a big fan of programming in Tcl, the "Tool Command Language", although it is distinctly out-of-fashion these days.  When I have the freedom to choose, I tend to use Tcl for anything that doesn't need to run at maximum possible speed (and probably C++ for anything that does).

One of my colleagues at Bloomberg once asked when I would give up writing utilities in such an ancient language as Tcl and update myself to something more contemporary like Python.  I should perhaps have replied "I find your lack of faith disturbing" but I just said something lame to the effect that such an "update" would make me less productive 😉.

Over my 47-year involvement with computing, at various times I have been enthusiastic about several different programming languages:

  • St. Andrews Static Language - the first practical implementation of a pure functional programming language anywhere, which I just happened to get the chance to use in 1975-6.
  • Modula-2 - a very clean, predictable, understandable conventional algorithmic language.
  • Prolog - the classic PROgramming in LOGic language, yet another fundamentally different yet consistent paradigm.
  • Perl - quite the opposite of all the above, a very "hacky" language based on practicality not purity, great for solving certain types of problems quickly, but really not scaling up nicely at all.
  • Tcl - "Tool Command Language", for me this hits the "sweet spot" between all of the above.
Programmers who like Tcl tend to think of it as being clean, logical and consistent.  However the majority tend to reject it, complaining about "quoting hell" and various awkwardnesses which basically come down to it being too different from what they are used to.  Really Tcl has a radical minimalism which makes it genuinely different from the common patterns that most programming languages follow.

Most programming languages blend syntax and semantics.  Each language construct (e.g. if-then-else for conditional execution) has individual rules for how it is written (syntax) and how it operates (semantics).  The language definition as a whole includes all of these specific elements of syntax and semantics.

In contrast, the essence of Tcl is a very small and simple core which defines only how to define and use variables, data values, commands in general, and events.  The only syntactic rules are those which define how to invoke a generic command and pass data to and from it.  These are documented at man Tcl, there is no special syntax for specific commands.  All functionality is defined as the semantics of individual commands.  Flow control is done by commands which take other commands as their arguments.  So if-then-else functionality is provided by a command called "if" whose arguments are the condition to test, the code to execute when the condition is true, and optionally the code to execute when the condition is false.

This design can be cumbersome in some ways.  For example, the core has no syntax for arithmetic expressions, this is delegated to the command expr, which the programmer has to explicitly invoke in various places where some calculation is needed.

However this division of concerns creates a unique flexibility.  Commands can be created or redefined on-the-fly. To give an extreme example, it's perfectly possible to redefine the "if" command to reverse its logic.  More constructively, before Tcl added built-in commands for object-oriented programming, many people exploited the language's flexibility to make their own support for object-orientation.

I suspect this modular design has also enabled Tcl to evolve more smoothly.  Since it was originally designed, Tcl has incorporated many innovations (caching of optimised internal representations for code and data; unicode support; multi-threading; coroutines; fully-virtualised filesystem operations; decoupling of versioning for language extensions, etc.) with almost no disruption for existing running code, something which Python still struggles with.

I should say that Lisp has many of the same attributes that I'm claiming for Tcl.  One difference is that historically, Lisp systems tended to be conceived of as a universe of their own, with little regard for interoperation with anything else.  Tcl on the other hand started life as an extension language intended to be embedded in other software, and so has strong support for integrating with other systems on multiple levels.

Finally we have the cross-platform GUI (Graphical User Interface) support provided by Tk.  This can be used from other languages, but is most closely integrated with Tcl.  For an example of the kind of handy but lightweight tools that can easily be put together with the Tcl/Tk combination, see Diskusage.

7 comments:

  1. I feel identified with "...when I would give up writing utilities in such an ancient language as Tcl and update myself to something more contemporary like Python..." given that I am still using Tcl after so many years!

    ReplyDelete
  2. I've often thought of Tcl as a "stealth Lisp" due to its relative semantic simplicity. That said, even though I'm a fan of the language and have used it in commercial applications, the Tk bindings are not something that I'd personally call out as one of Tcl's great strengths.

    ReplyDelete
  3. This kicked off some worthwhile discussion at "Hacker News" - https://news.ycombinator.com/item?id=24897326

    ReplyDelete
  4. command # Why I can not write like this in tcl

    ReplyDelete
    Replies
    1. some tcl command ;# with comment

      Note the semicolon.

      Delete
  5. I would feel a lot better about praise for Tcl if it delivered on its nascent premise. Tcl is so functional it ought to be functional, but it is not. It is a confused mash. For 20 years I have looked forward to the release of the functional version 9 (10?) but it has not happened. I still use Tcl whenever I program but I cringe with almost every line I write so it is not a pleasant exercise. It has put me off programming.

    ReplyDelete
    Replies
    1. Don't let TCL put you off programming man, all I ever used it for was automating commands to be sent to large numbers of switches and routers. You need to pick your language for what it's good for as the need arises.

      Delete

Fundis - FUNctional DIStributed processing

This is a technical post about a project I've been thinking about on-and-off for a while.  The idea is to use  Redis  as the middleware ...