I can't believe I'm praising Tcl (2008)
yosefk.com
yosefk.com
[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.
Although, I'm guessing now that Python and Rust are becoming BFF, https://tauri.app/ will become a more and more attractive option.
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
Some people would even find some of the built-in ones perfectly satisfying, I even know some people who love the classic Tk look (https://wiki.tcl-lang.org/page/List+of+ttk+Themes)
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.
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.[0]: except satirical/joke languages
[1]: https://www.eecis.udel.edu/~vsaxena/courses/ece697A/docs/OCE...
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.
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".
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".
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.
Travel back in time to when the parents of the person who created that file met... the rest is left as an exercise for the reader.
No idea if it'd survive Tcl or not.
Perl has strong support for that: https://perldoc.perl.org/perlop#Quote-Like-Operators
You can basically use any character as a delimiter except whitespace.
All of these lines are equivalent:
$str = 'Hello, world.';
$str = q{Hello, world.};
$str = q[Hello, world.];
$str = q(Hello, world.);
$str = q<Hello, world.>;
$str = q|Hello, world.|;
$str = q!Hello, world.!;
$str = q#Hello, world.#;
$str = q%Hello, world.%;
$str = q=Hello, world.=;
$str = q 7Hello, world.7;
Note that when you use a letter or number (actually any character that's legal in an identifier), you need a space after the "q".You can also do it with other types of quotes, like double quotes (that support variable interpolation). These are equivalent:
$var1 = 'abc'; $var2 = "Value of var1 is $var1.";
$var1 = 'abc'; $var2 = qq[Value of var1 is $var1.];
And you can also do it with regular expression matches: if (/pattern/) { whatever(); }
if (qr|pattern|}) { whatever(); }
and substitutions: s/pattern/replacement/;
s|pattern|replacement|;
sed also has something similar: echo abc | sed -e 's/abc/def/'
echo abc | sed -e 's#abc#def#' $str = q 7Hello, world.7;
whew, I would not want to be in the business of lexing perl> sed also has something similar:
I also recently learned that one can do the same in the "pattern match" case (not just with `s`) by using a backslash, as in:
printf 'a/b/c\nd/e/f\n' | sed -ne '\_a/b/c_p'
the man page says "any character" and sure enough, `\ a/b/c p` works alsoHow on earth would you create syntax highlighters and other tools for this language?
Hence the saying: the only thing that can parse Perl is Perl :)
It also seems <https://github.com/Camelcade/Perl5-IDEA/blob/2023.1.1/plugin...> that one can have line comments in there, too
my $str = q #what is happening here
7Hello, world.7;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.
the '90s were some wild times in internetland.
https://git.savannah.gnu.org/cgit/dejagnu.git/tree/
I still use it for testing software. Add in expect and it is fairly simple to write tests against TCL applications (I do it all the time).
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.)
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.
`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.
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.
(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 think jq brings a lot of that cool awk mentality forward. I'm consistently impressed by all of the neat things it can do.
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.
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.
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").
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?