Barely related but Tk/Ttk (in particular tkinter[1]) is criminally underrated for GUI tools. There's a fairly solid cross-platform GUI toolkit right there in the Python standard library and it's even native on Win32 and macOS (meanwhile there are e.g. bootstrap-like skins for it in case you don't like the Motif-look on Linux). There's really no need for every small Python GUI tool/script to require PyQt/PySide/wxPython and the non-wheel packaging shenanigans that go with that.
[1] tkinter is actually a bi-directional Tcl <-> Python binding under the hood, all the binding code on the Python side is just classes and every method is just a thin wrapper around calling into Tcl.
Agree. ime. Tk/Ttk tkinter is sufficient for 99% of cases and the syntax is as simple as possible. Its stable, mostly backward compatible and fast. Also a breeze to maintain.
It uses the native theming APIs to draw the widgets in a mostly native-looking style, but (unlike e.g. wxWidgets) it doesn't use native widgets, so it doesn't behave quite like native applications.
But I agree that it's pretty neat. And the default theme on Linux has been updated and now looks more like some old-school GTK themes (which I like) than Motif.
I haven't checked for PyQt/PySide but the Linux wheels are more-or-less distro-specific, they're not manylinux wheels. I don't think a compliant manylinux wheel (i.e. one that includes all libraries beyond those of the manylinux2014 reference platform) is even desirable, because gtk doesn't really like being shipped with applications, it wants to load plugins and themes from the system etc. Qt is similar - a Qt app that ships its own version of Qt will always have issues fitting in with the system Qt LAF.
It of course depends on what the target is, exactly. If you don't care about looking "native", for whatever little meaning that has had for the past decade, you can just use whatever theme you fancy with Ttk. The theming engine might not be as powerful as Qt's, but it's certainly good enough for emulating a modern flat-look UI: https://github.com/israel-dryer/ttkbootstrap
One of the greatest things in Tcl is that I do not need to worry about escaping quotes in strings because of the {} syntax. Working with filenames with spaces is a breeze. And lists being first class citizens instead of an afterthought like in shell scripts.
Too bad I only learned it use it because it is the only scripting language the big EDA suites support.
Your comment made me curious, so I installed the Perl plugin for IJ <https://plugins.jetbrains.com/plugin/7796-perl> and sure enough, it parsed that str assignment correctly. My hat's off to them!
Thanks. TIL. I also started to use perl because it lets me write dirty one-liners to transform text on the fly. It's a fresh change from Python and its mandatory whitespace usage.
The fact that I learned Tcl because of Vivado is probably why I don't like it. I'll probably never like it, but I can at least admit it has some nice features that make sense for an embedded scripting language.
But I've never seen anything more vile[0] than Cadence's "Ocean" scripting language[1]. It has such contempt for the user. For example, when learning you might notice
command(
is ok but
command (
is a syntax error. You then might conclude that the language is trying to be strict and help you write correct programs. But then you realize that
"]
is magic syntax which closes all previous strings, and it just gets worse from there.
That is because SKILL is really an scheme under the hood. And somebody had the bright idea of making the syntax more "user friendly" (read: more like C) by inventing a rule that "foo(bar)" parses as "(foo bar)" while "foo (bar)" parses as "foo (bar)". IIRC there also is another similar rule for when expression is parsed as infix.
Right bracket with the meaning of close all was used in some lisps because somebody did not like the long runs of closing parens at the end of definitions.
In my personal life, I've discovered to name some files with (the most common) punctuation. I've taken to using the full-width unicode variants. These work on Mac, Windows, and Linux. They don't seem to cause problems for any software that can handle utf-8 correctly. Looks like there are curly braces in the full-width stuff... it'd be \uff5d looks like.
The real power was unlocked with uplevel, upvar and switch regexp for a variety of reasons. I miss sane language extensibility. It was meh in clojure by comparison and too much in scala.
This has not been correct since Tcl 8.0 debuted circa 1999. 8.0's Tcl_Obj system allowed for lists to be proper O(1) integer indexed arrays while also retaining compatibility with 7.x's "specially formatted strings".
And even for 7.x where lists were just "specially formatted strings" they were not simply "semicolon separated" strings, the special formatting was more complex than "semi-colon delimiter".
Nope. Semantically they are still semi-colon separated lists.
The fact that recent official TCL engines include performance optimisations does not change that fact, nor does it fix most of the issues with "everything is a string".
> they were not simply "semicolon separated" strings, the special formatting was more complex than "semi-colon delimiter".
Yes of course it needs quoting so that semicolons can be included. Thanks for pointing out one of the downsides of "everything is a string".
> Nope. Semantically they are still semi-colon separated lists.
Double nope. Tcl lists, even when they were specially formatted strings in 7.x versions, were never "semi-colon separated lists". For all but the simplest lists the special formatting was and is much closer to LISP s-exprs, only using {} instead of () for the formatting delimiter. Which was how Tcl's lists, just like LISP lists, can represent nested list structures, which plain semi-colon separators cannot.
> The fact that recent official TCL engines include performance optimisations does not change that fact, nor does it fix most of the issues with "everything is a string".
But it does mean that in modern Tcl versions, your code does not have to pay the price of parsing that special string more than once, removing the biggest issue with "everything is a string" (the performance issues in 7.x versions).
> Yes of course it needs quoting so that semicolons can be included. Thanks for pointing out one of the downsides of "everything is a string".
That is no more a downside of "everything is a string" than needing to quote an ASCII double quote (") in a C string literal because double quotes delimit the literal itself is a downside of C string literals. The special characters in any language will need some method of quoting to be used as themselves in positions that they would otherwise be interpreted as part of the language grammar.
Another instance of higher level language mixed with low level programming that I found quite refreshing is MicroPython on modern MCUs. Lately I had to develop a driver for a LoRa chip, and it was quite a good experience to interactively code/debug it in a REPL console.
I guess I must be thoroughly dain bramaged if my first reaction to Tcl was "wow I love this" rather than the seemingly more common "eww this is disgusting".
my first job had a bit of linux aolserver and tcl for config and the web app, and writing cross-platform installers using tcl/tk. it was actually pretty nice.
this was in the late 90s... it was a perl/tcl/java shop, and java was only used for some oracle dependencies that were set in stone due to the entire backend engine being written in stored procedures (lol). the native application itself was for windows, developed and cross-compiled (i can't remember what they had to compile - maybe a static version of the tcl or perl runtime or something like that) on linux using a bunch of stuff including cygwin.
i can't believe they trusted a teenager to write their installer but it was really simple. pick a path, and it dumped the uncompressed contents into it, set some registry values, created a desktop shortcut, and ran the executable. they replaced it with that ubiquitous windows installer that everyone used back then a couple of years after i left for college when the install started bundling other commercial apps the users requested. probably some software marketing deals drove that once they hit some traction.
also, i remember getting to use a sun workstation to develop oracle ETL scripts in perl which was pretty cool. i think at one point i had a linux dell workstation and sun workstation...
that first job taught me how to actually ship software and work in a team with source control and software and infra engineers who actually knew what they were doing which was amazing for a 16 year old. they even ran their own mini datacenter in a back room before the explosion in colo facilities and good fiber networks. the whole thing ran off of a pair of T1's.
I see these Tcl posts from time to time here and I once had to work with a legacy code base build with that language and it wasn't good. Learning the language is not intuitive and the worst of it all is that I wasn't able to write any tests which would have helped to refactor that mess. If I recall it correctly there just wasn't a way to write tests because it's not supported.
> Learning the language is not intuitive and the worst of it all is that I wasn't able to write any tests which would have helped to refactor that mess.
Tcl is one of those languages that's centered heavily around a single dominant concept. In Tcl's case, the idea behind the language is that everything is a string and most of the computation is expressed through various forms of string substitution.
The earliest versions of the language were actually implemented this way. Indexing into an array required the interpreter to parse through a string representation of the array looking for the element you requested. Interpretation of code worked the same way - it parsed your code as it went along. Later versions (>=8.0) added the notion of "dual-ported objects. These gave the interpreter the ability to cache more efficient representations of various kinds of object, while retaining its 'string gestalt' principle.
The net of this is a language that's almost totally at odds with the way people think about coding, and yet has a great deal of deep expressive power that's easy to miss. (It's easily possible to do things in Tcl that might have otherwise been limited to something like a Lisp macro or some kind of preprocessing/code-gen technique.)
This general approach can make the experience of using the language initially very difficult, since it's so unexpected and different from the usual previous experience. If it sticks, though, it can be a seductive sort of environment in which to work. Whether or not this is good or bad language design is a bit of an open question, but I'm glad languages like this exist.
> If I recall it correctly there just wasn't a way to write tests because it's not supported.
It's easy enough to write tests directly in C. There are plenty of ways to do tests in Tcl also. (Many of which are benefited by the string nature of the language I describe above.)
I had the opposite experience. One of my first jobs was to port a legacy TCL GUI to Java Swing.
Even though I understood exactly what the TCL was doing, the Java port was 20x more lines of code, and 100x slower. I spent a few months beating my head against the poorly designed padded cell that is the JVM, and then it was 40x longer, and 10x slower.
That's more an indictment of java than an endorsement for TCL since you were dealing with something already working. I'm sure perl/tk, qt, fltk or many others would have been a much better experience.
Tcl has an excellent unit test suite, Tcltest, that's remarkably easy to use. It's been around a couple of decades. I've written more test cases using it than I could easily count.
Yeah. You sometimes hear rules like "never write tests outside a framework," but this advice is aimed at the junior dev who doesn't want to learn the tooling, not at someone who is necrocoding in a 30 year dead language and needs to decide between loads of copy/paste and rolling their own testing framework (which would get used once, leading to amortization difficulty). Sometimes the constraints really do call for loads of copy/paste, and that's OK.
`uplevel` permitted modifying the calling environment, enabling injection of locally scoped dsls. And trivial dsl customization (subset, extend, modify). And optioning the imports.
Standalone executables were easily created, with an embedded filesystem.
Programming language evolution seemingly suffers from a lack of accessible memory and reflection. I wonder if LLMs might be leveraged to derive sort of a "virtual C2-wiki" view over existing collaboration infrastructure (HN lobsters, /r/ProgrammingLanguages /Haskell etal, LtU, SO, awesome lists, programing blogs, language wikis, research papers, etc)? So one could ask about locally scoped dsls, and see answers, and relevant discussions, and links to related asks, rather than manually searching for, browsing, and synthesizing fragments of such.
Interesting article - and the writing style's entertaining, too.
I can certainly relate: my first introduction to Tcl was the scripting in Quartus, and my intial reaction was mostly "Ewwww!". But once I figured out which kinds of brackets did what and started to appreciate things like being able to cascade timing constraint files and have variables defined in one file be visible from subsequent files, I developed a grudging respect for it.
The grudging respect gave way to outright admiration once I started to appreciate the minimalism and simplicity, and discovered just how trivially easy it is to write a Tcl extension or integrate it into a project as scripting language. I might think twice about using it outside the EDA space, but within that world I'd use it with no hesitation.
Honestly IMHO awk holds up better than TCL. But that's just me.
(which is not to say that awk is _better_ than TCL, they're different things. Only to say that for me TCL has been eclipsed by things like Python or Clojure, while awk still has a few places where it shines quite brightly indeed.)
I felt the same way the first time I worked with Tkinter/Tk/Tcl (Tkinter was my gateway). But I think that has just as much to do with the sorry state of Desktop GUI as it did with how awesome Tk is it make a gui with
I can't believe you're praising it either. Yes it's above the Bash and CMake gutter tier scripting languages. And yes it has an "oh that's a neat trick, now burn it and do it properly please" way of doing blocks.
But I don't think "not completely awful" deserves much praise. Especially because it has infected the entire EDA industry. It really should have died decades ago.
TCL is fine. It's easy to embed, small, and has a low memory footprint. Interop with C (or anything that knows how to interop with C) is very easy. It's powerful enough for complex automation, and simple enough that you can almost use it like a DSL.
It might not be the fastest language, but TCL is much faster than the things you typically see it used to automate. Certainly more than fine on any computer built within the last 15 years, even with all the string parsing.
It's stable, well documented, and has a huge codebase available on the internet. There is also a stable user community.
TCL has a foothold in the EDA industry, yes. I think that's mostly because "if it ain't broke, don't fix it". Vivado and Quartus might each be hot garbage in their own unique ways, but that's not the fault of their scripting language.
I admit that TCL is a litle weird looking, and it doesn't feel like any other language. It's closer to LISP than to C, and closer to BASH than to LISP. But it's powerful, stable, and entrenched. And beautiful in its own way.
But it is broken. It has a ton of gotchas, WTFs and confusing behaviour. I appreciate maybe there weren't many easy to embed languages in the 80s, but there are loads now! Lua is an obviously better choice.
Tell me one reason to use TCL over Lua (that isn't "we've always used TCL and can't be bother to change it").
Lua's a great language, and I've got nothing bad to say about it.
TCL is fine too though. I think its main problem is that it feels alien to people who haven't used it much. That plus the way that comments are treated by its tokenizer. :)
For new programs, the only reason to embed TCL would be if your audience already knows it. If I was writing a new piece of EDA software today, I'd probably still choose TCL because it would have critical mass with my userbase.
For existing programs, what's the benefit in switching? If you get beyond the "TCL is ugly" mindset, what benefit would Xilinx/Altera/Synopsys really gain by switching? Their whole userbase already knows TCL, and there are tons of scripts that are already written. Switching to Lua wouldn't add any new functionality, and it would be hugely expensive. It would also annoy their userbase, who would have to go off and rewrite all of their own scripts without any benefit.
I guess you could characterize that as "we've always used TCL and can't be bothered to change it", and you're not wrong. But I'd challenge the assertion that it needs changing. TCL has a big standard library, and an enormous amount of third-party code in the wild. It was even an important Unix system language for a while there. Today, TCL still lives on in Expect and Tk (generally wrapped by tkinter). It's probably lurking in lots of other places as well.
Would you tell the Welsh that they should give up their language just because English is more widely used? Sometimes a language takes hold somewhere, and it becomes part of the culture. Switching isn't impossible, but is the benefit worth the hassle?
[1] tkinter is actually a bi-directional Tcl <-> Python binding under the hood, all the binding code on the Python side is just classes and every method is just a thin wrapper around calling into Tcl.