The Tool Command Language Sucks
I felt inspired by “Why Does PHP Suck?” to name all the reasons why Tcl sucks despite Tcl already having lost all popularity. If you search for why Tcl sucks, you will only find Reddit posts and an old rant by Richard Stallman from 1994 who loves his competing LISP language which equally sucks for many of the same reasons.
No types, everything pretends to be a string
Internally it has but they are not reliable and you can’t access them. Often it means you will make separate variables to store your type information.
You will have to repeatedly name
which kind of variable each string stores before performing the most
basic operations on it. Other scripting languages, both object
oriented and less object oriented, do it a lot better. string
index
, lindex
and dict get
all contain the name of the type they act as whereas
other languages simply use var[key]
.
Comparisons have two sets of
operators: one for the strings (eq ne), one for numbers (!= == <
>)
Who is to blame? Lack of types.
Is the variable set to a useful value
or not? Even in C you can set a pointer to NULL
to indicate it. Not in Tcl. You will make a separate variable with a
bool or use [info exists]
together with
unset -nocomplain
. Which brings me to
the next point.
No boolean
Tcl has no bool. Just 1 and 0. You will mix them up with number variables.
Everything is copied by value
If you need a more complex data
structure or want to act as a reference, it will be a string with the
name of the other variable and then you’ll have to double
dereference it. No, $$var
does not work.
You have to use [set $var
]
.
If $var is {a} and $a is {b} then it will return {b}.
The advantage is that everything is basically already in a serialized state. You can save and load it without extra work.
No nested functions and lambda in a separate package
Most keywords are commands. Thus proc creates a function in the global scope. They can be renamed or unset but are still separate from variables and their scopes for no apparent reason. That means you can’t nest functions. Lambdas have to be required from a separate package because like many old languages, they can’t break old code by introducing new keywords.
Most things are not strings
Most things are variables or functions and the redistribution of markup from strings to variables and functions will create more work instead of less.
Other languages: foo() (in some without parentheses too) var "str ing" Tcl: [foo] $var string or {str ing}
Most of the time your function calls
will be nested even if you just set a variable: set
a [foo]
Bad syntax highlighting
To tools it’s never clear what will be used as code or just text, so the syntax highlighting in your editor code will often mark keywords words in strings and show code as one colored string.
Inconsistent standard library
Compare lset,
lindex, dict set, dict get
or
string map
.
Loops more painful than in C
C: for(int i=0;i<10;i++) {} Tcl: for {set i 0} {$i<10} {incr i} {}
Of course you could always reinvent the wheel for every script since Tcl allows you to write your own control flow functions but you won’t.
It’s metaprogramming capabilities are not that great
While the “everything is a string” philosophy might help somewhat because it means most of what you write will be a string at first, the execution order will still interfere with you making up a completely new language.
You will forget the dollar sign
Having to think about where a variable name retrieves a value and where it will be used as a reference to set a value adds an extra thing to reason about every single time and no matter how much you wrote, you will forget a dollar sign again and again.
Internal encoding mess
Tcl has some Unicode support today but if you load a UTF-8 text file with LF line endings in binary mode and perform any string functions on it, it will destroy your data. Many other languages do not have this problem.
set f [open uni.txt rb] puts [read $f] close $f
Hallo Wörld
Ruby:
f = File.open('uni.txt','rb') puts f.read f.close puts IO.binread('uni.txt')
Hallo Wörld
Hallo Wörld
Tk sucks
Tcl can’t be mentioned without its GUI toolkit Tk. If you need anything more than a window, a button and a simple text box then Tk sucks too.
Conclusion:
Tcl is dated and it’s good that it died. It’s cumbersome to read and write. — Oh but Tcl is small and has few rules! — Well Lua is smaller and has less rules if you factor in basic data structures such as hash tables and arrays.
And while, unlike Lua, Tcl can do basic stuff out of the box, for example list files recursively, you are better off using a larger more expressive language in those scenarios.