There's lots of new stuff, and some old cruft has been dumped, so some programs may need a few updates, but there's still a high level of compatibility. The page above links to release notes with details of what's in and what's out.
It may be easier to reason about when thinking of the way $(mount -o loop) works with .iso files -- a file that is a container for other files that one can mount as if it were a filesystem
I was expecting pathlib in Python <https://docs.python.org/3/library/pathlib.html> to have one since a lot of Python distributions ship the standard library in .zip files but evidently not. Python gonna Python in that way
Firefox actually used to ship with that same "jar:" protocol handler, too, and I made good use of it for reading the javadoc html which was shipped inside zip files and was indescribably easier than trying to manage all the .html files in a Java 8 SDK distribution. They made heavy use of this because a lot of their internals were in .xpi formats (which is also a .zip file) but they recently dropped it because Firefox gonna Firefox^W double down on some random shit other than making a sane browser
> Consider the naive attempt to clean out the /tmp directory.
> cd /tmp
> foreach f [glob *] {file delete -force $f}
> A file ~ or ~user maliciously placed in /tmp will have rather unfortunate consequences.
i learned a few new habits since then. i almost never use rm -r and i avoid "*" as a glob by itself. instead i always try to qualify "*" with a path, remove files first: "rm dir/*"; and then remove the empty directory. "rmdir dir/"
if i do want to use rm -r, it is with a long path. eg in order remove stuff in the current directory i may distinctly add a path: rm -r ../currentdir/*" instead of "rm -r *"
related, i also usually run "rm -i", but most importantly, i disable any alias that makes "rm -i" the default, because in order to override the -i you need to use -f, but "rm -i -f" i NOT the same thing as "rm". rm has three levels of safety: "rm -i; rm; rm -f". if "rm -i" is the default the "rm" level gets disabled, because "rm -i -f" is the same as "rm -f"
Bad:
rm *
Okay: rm ./*
rm /tmp/d/*
rm */deadmeat
rm d/*
Then again, I commonly use dangerous things like `mv somefile{,.away}` that are easy to get wrong, so maybe don't trust my advice too much. rm -rf "$TSTDIR"/etc
is pretty dangerous when you forget to set the env varI guess I'm not likely to type that into the shell, or if I do, I then tab-complete to expand it.
I could definitely see myself using that in a shell script, though. I tend to do validity checks there:
if ! [ -d "$TSTDIR" ]; echo "$TSTDIR not found, stupid" >&2; exit 1; fi
but that's kind of irrelevant, since if I need it to exist then I won't be removing it. Plus, I could totally see myself doing if [ -d "$TESTDIR" ]; then
rm -rf "$TSTDIR"/etc
fi
for i in $(find something); do echo "rm -f $i"; done
(bash example as my TCL is rusty)
I like it for two reasons. Find feels like it has more solidly defined patterns and recursion than shell globing and by leaving off the "-delete" it give me a chance to inspect the results before committing to my actions.
You can use "\rm" to invoke the non-aliased version of the command. I made "rm -i" the default using an alias and occasionally use "\rm" to get the decreased safety level you described. I think it is more convenient that way.
It has a syntax of your expectations, functionally existing as a set of boundaries, and you can hook it to always run as a wrapper for some set of commands. It essentially stages the wrapped command and if none of the boundaries are violated it goes through. Otherwise it yells at you and you need to manually override it.
For instance, pretend I'm ok with mv being able to clobber except in some special directory, let's call it .bitcoin or whatever. (chattr can also solve this, it's just an example). The tool can be implemented relying on things like bpf or preload
Originally I wanted it as a SQL directive ... a way to safeguard a query against doing like `update table set field=value expect rows=1` where you meant to put in the where clause but instead blew away an entire column. I think this would be especially useful surfacing it in frameworks and ORMs some of which make these accidents a bit too easy.
But this is stupid. These are computers, we can make whatever we want. Executing a delete or update should, if one desires, not have to be database knifeplay.
I don't disagree that it's impossible, but how do you get the syntax standardized at this point? Do you get various dialects, or an agreement between vendors? Look how slowly the standard moves, when do we get this where it's usable in most popular RDBMS?
Just implement it for one and if it works, the others will add it
Here's a list of 1,000 postgres extensions, it's not a big deal: https://gist.github.com/joelonsql/e5aa27f8cc9bd22b8999b7de8a...
Things are way more modular than they used to be.
I can probably do it again and just try to get attention for it.
One of those learnings, was that I never wanted to again use a dynamic language without any kind of JIT compiler for full blown web servers.
The language is great, rewriting Tcl libraries into C on regular basis due to performance issues not so much.
And you're not kidding about everything being a command - this here is some "what the fuck is wrong with you people": https://wiki.tcl-lang.org/page/comment
Including the truly stunning collection of:
- one must terminate the command with ; before one can comment
- one cannot have mismatched braces so don't try to comment out bogus code
- one cannot have a backslash in a comment but hey it's a feature not a bug because this is how they launch wish:
#!/bin/sh
# the next line restarts using wish \
exec wish8.0 "$0" "$@"
since the backslash is ignored by the shell but parsed by wishA Philosophy of Software Design:
This is huge! A big portion of why concurrency in Tcl was so dated and why the language was considered so non-performant was because it relied on `select` despite `epoll` and `kqueue` being available for at least a decade.
Tcl is one of my favorite languages because of how easy it is to get started with and how easy metaprogramming is.
another reason is that we don't know how to write fast tcl, as i inadvertently demonstrated in that thread
The "catch" is that the theming engine has its own new widgets, and so to be themed an application has to use the new API. Code from 1995 (or 2005) still produces GUIs from 1995.
Things may have changed over time. I no longer pay attention. Maybe I'll give it another try.
Anybody using it for something else and can speak to why you’d use it today? Genuinely curious; I don’t hate the language but can never bring myself to enjoy it either.
I spent ten years, from 2005 to 2015, programming almost entirely in Tcl/Tk and I loved it. Since then I mostly use it for casual scripts rather than for writing apps; but it's still my #1 choice when I need to do some scripting to automate something at the OS level.
I wouldn't do an end-user GUI in Tk at this point; but for in-house tools that need a GUI and don't need to be on the web it's hard to beat.
Two examples:
- Adding convenience features to the Cisco IOS CLI (e.g., ^D to exit).
- Implementing the back end of a native WPF Windows GUI application that downloads spooled print jobs from a third-party system that only provides remote spooler access through a full-screen interactive terminal application running over ssh. This application also makes use of another nice Tcl feature, its trivially-implemented remote protocol[2].
[1] https://core.tcl-lang.org/expect/index
[2] http://corex.tcl-lang.org/tcllib/doc/tcllib-1-18/embedded/ww...
BigIP iRules in F5 network appliances (and A10 appliances)[0], orchestration in Argonne National Labs super computer[1], Tealeaf[2], Python Tkinter[3] …
I use it day to day because it’s got a great balance of Lispyness and simple scriptyness, and a great C interface. It’s got a fine REPL, and can be built up (by writing in C) with extensions that are 100% first-class canonical Tcl, in good part (wholly?) because Tcl is such a simple language[4], and homoiconic[5]. A joy to develop in and use.
[0] https://community.f5.com/kb/technicalarticles/irules-concept...
[1] https://www.mcs.anl.gov/~wozniak/papers/Swift_Tcl_2015.pdf
[2] https://www.acoustic.com/pdf/Acoustic-Experience-Analytics-%...
[3] https://docs.python.org/3/library/tkinter.html
[4] https://www.tcl-lang.org/man/tcl/TclCmd/Tcl.htm
[5] https://stackoverflow.com/questions/6492704/what-exactly-doe...
It's strength is that you get to operate EDA tools as if they were shell script commands, like run_my_task -option_a -option_B
If you aren't designing computer chips, you have no reason to use it. It's a horrible language.
The sooner the EDA industry can get rid of TCL, the better.
A long time ago as a college student I used Tcl in an EDA internship. It was awful for reasons completely unrelated to Tcl. There was a library of tool-specific primitives. The primitives were badly documented, badly tested, and nobody actually understood how any of it worked except cargo-culting and copy-pasting each others' scripts. Code only worked on the happy path and there was almost no thought given to edge cases. There was no culture of code review so nobody scrutinized your code to find out whether you were using Tcl in the right way or not. I'll grant, though very lightly, that Tcl has more accessible metaprogramming facilities than Python which makes it easier to misuse than Python. Similar to how Ruby in the hands of a undereducated/bad Ruby programmer is also quite gross.
But I had the same issues using Perl in the EDA industry. The conclusion I came to was that code standards were just abysmal in EDA because code was largely seen as a cost-center activity rather than a profit-center activity as the real output was the ETL or the device and not the code that went into it.
I re-learned Tcl when I was older and when my time in EDA was a faint memory and I found the language a joy. It was remarkably easy to get started in and really easy to build an application out of. This experience further made me reflect on how bad the code culture in EDA was.
So I'm curious what specifically you'd see the EDA industry move to and how you think it would fix the problems EDA currently has with Tcl. Python, is the successor I imagine? That said my actual time in EDA was very short so I welcome the opinion of an actual insider.
As a language, Python is the correct answer.
And now, Python just has so much more widespread support. You can get any library you want in Python, with its millions of packages available. Want to do some AI processing on your schematics while printing out a graph? There are all sorts of libraries for that. You can't get that in TCL.
What an unfair statement to make; by no means is it an horrible language. Just because it doesn't fit your tastes doesn't make it "horrible".
That's like me saying having to start a line of Python with three spaces is annoying design which makes it an horrible language. Take your statement elsewhere.
I immediately moved my scripts to Python 1.0 when Python arrived on the scene because TCL (and PERL) were so horrible.
If it's personal preference, than fine. But that doesn't make it a horrible language for all. I enjoy TCL and Perl and I'm 35.
I don't touch Python because I don't enjoy it. And I coded with it when it was in early 2.0x in 2003. I'd rather learn Java.
- A backup app for an online sales application (inputs items and spits out a file);
- An app to fix files in a buggy POS for a large retail chain (this might have been used in thousands of machines, I can't recall the details now);
- A small app to copy Forms/Reports to the server, fire compilation, and push the new file to git;
- A wrapper for gs to help a media department easily join many PDFs into one file.
All these have a page or maybe two of code.There was Vignette, and we at Intervento had our Safelayer product, loosely based on AOLServer.
Apache and IIS plugins for hosting Tcl interpreter, running on Aix, HP-UX, Solaris, Red-Hat Linux, Windows 2000/NT, with support for Oracle, Informix, DB2, Sybase SQL Server, Microsoft SQL Server, Access (only for test purposes).
Development environment was based on Emacs, eventually there was one written in Visual Basic specifically for the product, with project templates and other kinds of goodies.
However we eventually hit the limits of using Tcl, and having to rewrite parts of the platform in C.
As it was, being a gold MSFT partner gave us access to .NET before it was announced to the world, and a plan to rewrite our product into C# took place.
With the learnings of these experiences, and customisations done at client sites, the founders eventually moved on and created one of the best products for no code development still going strong nowadays, OutSystems.
Never used Tcl again since those days.
Now when it comes to Tcl, I use it for the above reasons because it is so convenient for writing scripts to use SQLite. In other words, it is my go-to wrapper for many SQLite applications. This is mainly related to (rapid) prototyping use cases.
From https://sqlite.org/tclsqlite.html :
> The SQLite library is designed to be very easy to use from a Tcl or Tcl/Tk script. SQLite began as a Tcl extension and the primary test suite for SQLite is written in TCL. SQLite can be used with any programming language, but its connections to TCL run deep.
In my (limited) experience, Tcl/Tk is great for basic stuff but I don't think you could do even a small part of what you can do with an html + css + javascript GUI.
2. I have seen very basic GUIs in electron just for the cross-platform nature of it.
Say you wanted to write a CAD app like https://www.onshape.com. There’s no way you could do it Tcl/Tk, is there?
Nedit (based on Motif) on the other hand was both very fast (faster than the Gtk2 Geany) and bug-free - it worked perfectly. But i wanted Geany because of the file browser sidebar.
So i wrote a small Tcl/Tk script to display a list of files using a filter in a directory and call Nedit to edit them when you doubleclicked. Also added a few buttons to call make, make clean, open a terminal, make a new file, etc and worked perfectly.
A few years since then i made a few improvements and modifications to this script and use it on my main PC whenever i want to work on C source code - though i use Krita instead of Nedit here (Krita has its own file browser sidebar but i find the way it works annoying - and doesn't have all the extra stuff i've added over time to the script).
The neat bit is that it reads a Tcl file from the home directory for "global" configuration (e.g. which editor to use, how to run terminal commands, etc) and then a Tcl file from the current directory for project-specific stuff, all of which having access to the main script's own procs for things like calling terminal commands, showing a few dialogs, etc.
I've uploaded the latest version of the script to my website a few days ago[0]. I've been mainly using it with Linux but a couple of years ago i also used it a bit with Windows using MSYS2 (with Notepad++ for the editor) and worked fine.
There is a screenshot on the site.
For me the greatest TCL contribution was Ousterhout's dichotomy: https://en.wikipedia.org/wiki/Ousterhout%27s_dichotomy or by the author himself: https://web.stanford.edu/~ouster/cgi-bin/papers/scripting.pd...
https://www.intel.com/content/www/us/en/docs/programmable/68...
The issue with languages is that memory, CPU, and disk in the early 1990s are still fairly expensive. You need a language that is small yet still complete. Even today, the only languages that really fit that bill are Scheme/Lisp, Tcl, and Forth.
The memory limitations releasing are why you see the "stringly-typed" scripting languages like Tcl, Perl, etc. from the late 1980s transition to "dynamically typed" languages in the 1990s like Python, VB, later Ruby, Javascript, etc.
Tk popped up because GUI development at the time was utter shit (web doesn't exist, VB6 doesn't exist, etc.). It is really hard to describe just how much better Tk was than anything else in the time frame.
This[0] vs (from memory w/o a computer atm…):
#!/bin/env wish
button .b
.b configure -text “push me” -action {puts “don’t push me!”}
pack .b
[0] https://users.cs.cf.ac.uk/Dave.Marshall/X_lecture/node5.html...======
#include <Xm/Xm.h>
#include <Xm/PushB.h>
/* Prototype Callback function */
void pushed_fn(Widget, XtPointer, XmPushButtonCallbackStruct *);
main(int argc, char **argv)
{ Widget top_wid, button;
XtAppContext app;
top_wid = XtVaAppInitialize(&app, "Push", NULL, 0, &argc, argv, NULL, NULL);
button = XmCreatePushButton(top_wid, "Push_me", NULL, 0);
/* tell Xt to manage button */
XtManageChild(button);
/* attach fn to widget */
XtAddCallback(button, XmNactivateCallback, pushed_fn, NULL);
XtRealizeWidget(top_wid); /* display widget hierarchy */
XtAppMainLoop(app); /* enter processing loop */
}
void pushed_fn(Widget w, XtPointer client_data, XmPushButtonCallbackStruct *cbs)
{
printf("Don't Push Me!!\n");
}
Lua?
It's used in (and used for?) a lot of embedding:
Big missed opportunity for Tcl was the lack of a solid version of Tk for classic Mac (30 years ago). Would have made early Python less essential.
* Extremely consistent and elegant syntax - whole syntax/grammar is described in 12 rules in a single man page (Tcl(n)) of 150 lines and there's no reserved keyword. Nearer to CL than Python on that point.
* Homoiconic through strings (like almost every language with eval) but most importantly, through "list-like" strings.
* Official man pages! No web-only and spec-like doc like cppreference nor lackluster "minimalist" stuff like pydoc (compare `pydoc print` with `man n puts`, for example).
* One of the simplest if not the simplest interaction with C, letting you write C plugins very easily (with critcl and swig to help).
* Not slow, not fast. In the same ballpark as cpython or Perl; doesn't need a tracing garbage collector, refcounting does the job since no cycles are possible by design (worse for throughput, but lighter runtime).
* Fun type system that is superficially "everything is a string" (like sh) but in reality "everything is a tagged union with on-the-fly conversion when needed and a guaranteed string representation". Allows for transparent serialization (`puts $mydict stdout` <=> `set mydict [read stdin]`), like CL's read/write.
* Powerful introspection through `info` (mainly). Allows for stuff like getting the name/body/arglist of a procedure, get all the registered procedures, know if a variable exists, get information on the stack frames and their content, etc... Together with `trace`, you can even write an internal debugger in few lines.
* Procedure arguments are passed by pointer with a copy-on-write system: don't modify the argument and you don't get any memory copy. To you, it just looks like regular passing by value.
* Modifying the procedure arguments is done via `upvar`: in Tcl, a variable reference is just a name (string) attached to a relative stack frame number, quite elegant considering the language's core concepts.
* If you use at least the builtin extensions (thread, http, tdbc, tcltest, msgcat) and the very basic tcllib/tclX/tclUdp/tklib packages, you're almost set for life. Personally, I also recomment the very convenient tclreadline, tdom, pipethread, tablelist and tclcurl.
* Channels is one of the cleanest I/O implementation I've ever used with some cool features:
- Transformations allowing filters like deflate/zlib/gzip or TLS to be put on a channel (see `transchan` for the API).
- Reflected aka virtual channels, to make your own channels. Basically like glibc/BSD's unportable fopencookie/funopen or CL's gray streams.
- Centralize a lot of ioctl/fcntl mess and even more (like defining the EOF char) in `chan blocked/configure/pending`.
- Integration with the event loop via `chan event/postevent` allows for a nice callback oriented approach to sockets and pipes.
- Other third-party channel types include pty (expect), random, memory or fifo (memchan).
* Builtin event loop (see `after`, `vwait`, `socket -server` and `chan event`) for powerful and seamless concurrency/command scheduling. Much simpler than Python's very "AbstractBeanFactory" asyncio.
* An elegant thread extension consisting of an interpreter per thread and no raw access to other thread's memory. Comes with both simple (`thread::send/broadcast/transfer`) and performant (`tsv`) synchronization/communication facilities.
* Finally a sane, light and portable (even more with Tile) GUI toolkit: Tk.
* One of the fastest Unicode aware regex implementations, written by Henry Spencer himself. Has its own greater-than-POSIX-ERE syntax called ARE, not as complete as PCRE (lacking lookbehind constraints, most importantly), but still great for an hybrid NFA/DFA engine. Performance comparison with Perl: https://github.com/mariomka/regex-benchmark/pull/44.
* `uplevel` (eval a script in a different stack frame) and `tailcall` (replace the current procedure with another command) let you augment the language by implementing control structures and keywords yourself. Inferior to CL's synergy between unhygienic macros, "naked AST" style homoiconicity, symbols as first-class objects, gensym and quasi-quoting, but still quite powerful.
* Safe interpreters let you do very fun things like config files in Tcl with limited access to the machine and master interpreter.
* Recent versions (>= 8.5) really embraced FP with:
- Real lambdas (but not closures, these have to be emulated) through apply.
- Purer hash maps (dict) than ugly sticking-out-like-a-sore-thumb arrays.
- Lisp style prefix arithmetic (allowing for `* 3 [+ 1 2]` instead of `expr {3 * (1 + 2)}`) including sane behaviour for more than two (reduce) or zero (neutral element) arguments.
- Builtin map/filter (lmap) with 8.6. See https://wiki.tcl-lang.org/page/Functional+Programming for more.
* Multiple more-or-less powerful OO systems (now based on the builtin TclOO): [incr Tcl] for C++ style OO, XoTcl for a take on CLOS or Snit for something Tk oriented.
* Some massive issues on the top of my head: lacking a LSP/SLIME equivalent, the warts of the weird type system (no way to differentiate between atoms and single element lists or evenly sized lists and dicts), missing metaprogramming facilities like quasi-quoting, no official support for UDP and UNIX domain sockets, no GC for class instances (cf https://core.tcl-lang.org/tips/doc/trunk/tip/550.md), no FFI in core, subtly broken exec (cf https://core.tcl-lang.org/tips/doc/trunk/tip/424.md and https://core.tcl-lang.org/tips/doc/trunk/tip/259.md)
Here are some project I made with it, still worth using compared to CL which is my true love, simply because its stdlib is better suited for a lot of tasks:
https://git.sr.ht/~q3cpma/mangadex-tools
https://git.sr.ht/~q3cpma/rymscrap
https://git.sr.ht/~q3cpma/lemonbar-tcl
https://git.sr.ht/~q3cpma/tcl-misc
> * Safe interpreters let you do very fun things like config files in Tcl with limited access to the machine and master interpreter.
I keep looking for similar functionality in Python (the scripting language of choice for many, nowadays) but I am always disappointed.
For a long time it was the only way to get a decent IRC bot going, because eggdrop[0] was a Tcl wrapper around a small C core, but the only place I've seen it in the wild other than IRC bots was in the Xilinx toolchain and once when I was in undergrad some TA was using it to get telemetry from Tektronix oscilloscopes in the robotics lab.
Nice to see a new release coming out not too long after such a question :)
The starpacks/starkits for packaging apps together are really nice.
For anyone interested there’s a fork of the Tcl Dev Kit at: https://github.com/bandoti/tdk
This allows one to package applications with shared libraries and all bundled together.
OpenACS [2] is the main project of, which has existed since 1997 and that alone is highly powerful in what it can do with. Especially when coupled with TCL. It's still maintained and now supports TCL9 too!
Javascript, TCL and NaviServer (and which has it's own modules such as DNS Server, LDAP, Mail really makes an powerful tool.
If you're looking to get in to TCL and Web Development, you can really create fun with the two combined. I highly recommend that if you wish to dabble with something on the side for easy learning and plentiful features. Go take a look.
[0] https://wiki.tcl-lang.org/page/NaviServer
https://github.com/naviserver-project/naviserver
[1] https://news.ycombinator.com/item?id=35648805
https://www.linuxjournal.com/article/6164
Funny thing is I remember taking some free classes sponsored and taught by ArsDigita in an office they had in Pasadena, CA (or was it Glendale....???) they weren't too deep or long, but nice introductory stuff.
"Interesting footnote: the founding of Netscape occurred at the same time I was deciding where to go in industry when I left Berkeley in 1994. Jim Clarke and Marc Andreessen approached me about the possibility of my joining Netscape as a founder, but I eventually decided against it (they hadn't yet decided to do Web stuff when I talked with them). This is one of the biggest "what if" moments of my career. If I had gone to Netscape, I think there's a good chance that Tcl would have become the browser language instead of JavaScript and the world would be a different place! However, in retrospect I'm not sure that Tcl would actually be a better language for the Web than JavaScript, so maybe the right thing happened."
This is a fantastic insight and put very well. Thank you.
New platforms unlock rare opportunities for new languages that have no baggage and can focus on fully exploiting the new platform.
https://sunsite.icm.edu.pl/pub/programming/tcl/plugin/
I'm pretty sure some fellow students came into our computer room before that, "look now there even is a TK plugin for Mosaic!". it was not in "look it's like gopher but with a mouse!" days, but not that much later.
however you of course had to _do_ something to use it, while JavaScript came out of the box (once it was there).
Absolutely. I would have hated to see things like
set x [ expr $y + $z ]
all over the place. (As a command language, this is not so bad.)How does Tcl fare under these criteria?
I think of it as Lisp for C programmers.
So: is the language implemented mostly in itself? No, it's mostly implemented in C. Is there a minimal amount of magic? No; the amount of magic you can do is effectively unlimited.
I might be mistaken, but I think the OP was asking if there is surprising magic (I.e. special cases/considerations) built into the language, in which case I’d say, “No, Tcl is not “magical”, but surprisingly simple and regular.” That said, indeed it’s powerful in its application of its primitives, but you do still need to mind some things (don’t pretend* you can quote better than the quoting engine, don’t pretend* you can do lists better than the list processor, …). Not magical though - very understandable.
*rules are meant to be broken, blah, blah, but the “gotchas” are new practitioners falling into this, or advanced cases, falling into this…
sorry, https://news.ycombinator.com/item?id=41663259 does a much better job answering than my link