I have a strange test for languages - I tried some of them being drunk (a litre of some nice tripel). This test tests how effective can you be with diminished higher-order thinking, or, in other words, how much of your mental ability each tested language takes from you.
Tcl has immutable proc arguments - if you pass somewhere a value you can be sure the value at caller's site stays the same. It happened that this means a lot and one can (semi)successfully program in Tcl while being drunk.
Every language where arguments' values modification is visible to the caller is much worse in that regard, these are C, C++, C#, Java, Python and Perl (and many more). Aother bad feature is a null pointer - Per is better here.
Tcl does not have modifiable argument values except you are really want them (upvar and uplevel). It also has multivalue assignment in the form of "foreach {resultpart1 resultpart2} [procedure arg1 arg2] break" (or you can invent your own mutivalue assignment procedure). This makes building composable libraries quite easy.
[upvar 1] and [uplevel 1], which, respectively, link a variable in your caller's stack frame to one in yours and run a command in the caller's stack frame, usually compose nicely. They are Tcl's replacement for macros and the lack of a compile time/run time distinction makes them, in a way, easier to reason about. However, [upvar N] and [uplevel N] aren't limited to N = 1, your immediate caller's stack frame. You can reach up an arbitrary number of stack frames. It allows you to design really complicated control structures. [upvar] links also nest. You can fall into a pattern of carrying around some sort of a context or configuration data with nested [upvar]s like a poor man's Reader monad. Both are difficult to debug when they go wrong and should be implemented with care and only when necessary.
Since version 8.5 Tcl has a built-in command for assigning list elements to variables:
lassign [procedure arg1 arg2] resultpart1 resultpart2
Conveniently, it also returns the remainder of the list if there were more list elements than variables. It leads to the idiom set list [lassign $list foo bar baz]The fact that "everything is a string" is cute and odd but the end result is really closer to shell scripting than a real object-oriented language like Python. You routinely have to deal with string/list quoting and constructing complex data structures is tricky if they have to be represented with just strings and hashes.
Sure: it's flexible and you can reimplement all the features of a high-level language but I'd rather use a language which has all the features already.
And yes - the list quoting rules are weird! No doubt about that.
Without dictionaries complex data structures are quite difficult, and people will abuse the heck out of the language to create them. I was just looking at an example where some poor engineer was inventing a "data structure" by using string manipulation to create & modify variable names. Some of the variable names he derived were also defined as globals, so there was that too.
Prior to dictionaries, tcl only had arrays, which are the least string-like things in the language.
Lists might be "native" in the sense that the interpreter knows how to deal with them but in the data model there is no distinction between a "string" and a "list of strings". A list is just a space-separate string with quoting rules and the difference is entirely in manipulation.
It's easy to make quoting mistakes so a program might start breaking when arguments contains spaces: this almost never happens in languages other than shell.
This has not been true since the release of Tcl 8.0 that added the Tcl_Obj subsystem.
Lists in modern Tcl (8.0+, with 8.0 released in 1997) are proper O(1) indexed arrays. Yes, you can still request from Tcl the 'string' representation of the O(1) indexed array, and the result you get is the old (pre 8.0) "space-separate [sic] string with quoting rules" variant that will parse back into the O(1) indexed array later if you want.
But Tcl lists have not been /only/ those strings for a very long time.
I hope they will use something like hash-array-mapped trees someday. It will make things much faster.
If you are dealing with quoting issues that's probably due to you using an older version like 8.3 or 8.4. Give a newer version a shot!
Basically, in Tk, you can add a tag to an element of your drawing in canvas and assign mouse (or keyboard) event handlers to change colors or other attributes on entry and exit of mouse cursor.
I made a OO/relational database schema visualization in Tk, it was breese to navigate - once you hover over a relation, you can see classes highlighted; follow highlighted relation to get to them. And once you highlight class of objects you can see to which relations it belongs.
It tooks two foreach loops to get that behavior. As far as I know, HTML5 canvas does not support that out of the box.
I don't have anything against tcl per se, but I can't think nearly effectively about anything because tcl doesn't really live anywhere else that I work. I can appreciate that it has the audacity to thrive in the tools I have to use, but I always sort of pine for what could be.
What is the "could be" that you pine for?
It's nothing against TCL, and it no doubt has the power to do it, it's just up I do FPGA stuff, python is my swiss army bludgeoning device. It's just like EDA tooling is like, the #1 place where I wish python lived, but it's TCL's stronghold.
I really like TCL, I've been using it in conjunction with NaviServer known as AOLServer back in the day (which mind you has some interesting history).
TCL is a fun little language and combined with Navi -- you can really create some crafy webapps.
I haven't used Tcl for maybe 15 years, but if I recall correctly upvar was basically an alternative to lack of pointers.
What it was doing was giving you access to a variable from specific stack frame.
You could say I want to access variable from the function that called me.
upvar and it's interesting syntax allowed to create new "statements" for example in earlier versions of tcl (because looks like it was added later) you could implement try-catch "statement" and it would behave as if it was part of the language.
This is one of the things I miss most when using other languages. Outside of actual lisps (of which I consider Tcl to be one), there's very few languages that allow you to build your own control structures. Ruby comes close, but doesn't really have the same flexibility.
TCL just seemed to fit and discovering naviserver could do "register domain/home execute procedure return html" without having to create a mess of routes, models and all the rest just kind of made me happy.
There are implicit "OR" statements between those sentences.
Example: suppose a newbie wants to use tk do make a quick-and-dirty GUI and leverage tcl's async event loop to make it responsive while processing a bunch of files. It's my experience that while this can be done it is less than easy.
I gave short presentation about applying this approach to scripts combining a responsive GUI with managing multiple parallel Expect sessions at www.eurotcl.eu/program.html#Macleod .
Tcl wasn't my first language, but it's near and dear to my heart. It's a little oddball for sure.
I can't decide whether it's Python trying to be Bash, or Bash trying to be Python. But it's surprisingly expressive.
Everything is strange about the syntax - from "everything is a string" to "expr" to the weird variable-assignment syntax.
It's also really tiny, and has a great async event-loop framework. It has built-in support for sockets and non-blocking I/O. It has a GUI toolkit that's pretty useful for making quick-and-dirty tools. It's incredibly easy to use interactively with a REPL. And it's still the scripting language of choice for the FPGA industry, which is where I got my start as a software engineer.
The Tcl community is small and stable. And the language just keeps soldiering onwards, in a gradual way. It feels like it's been stable and fully-realized for the last 20 years. No breaking API changes, no syntax changes. It just keeps on keeping on, providing automation to tools that need it. Tcl has outlived a bunch of newer languages, and I hope it sticks around for another 20 years.