Tcl is the best scripting language for the real but still productive hacker
(Scheme is not far).
* Extremely small - whole syntax/grammar is described in 12 rules in a single
man page (Tcl(n)) of 150 lines and there's no reserved keyword.
* Official man pages! No pydoc or cppreference garbage, here you almost have C
degree of exhaustivity.
* Kind of "unfashionable" language meaning basically no poz.
* At least two implementations with jimtcl being a very thorough embedded one.
* One of the simplest if not the simplest interaction with C, letting you write
C plugins very easily (with critcl, ffidl and swig to help).
* Comparable in speed to cpython, a bit slower than Perl5 and Lua. Has a
and a WIP/dead LLVM compiler (tclquadcode) for a big speedup in the far and
uncertain future.
https://wiki.tcl-lang.org/page/Tcl+Performance for more.
* Cool 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 unique string representation". Allows for some very cool things
like editing dictionaries as lists or lists as strings and transparent
serialization (`puts $mydict $chan` <=> `set mydict [read $chan]`).
* Talking about types, multiprecision arithmetic is transparently handled,
allowing you to do `expr {42 ** 1000}` if you just want to.
* Very 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 exist, get information on the stack frames and
their content, etc...
Together with `trace`, you can write an internal debugger in few lines. See
https://wiki.tcl-lang.org/page/Full+program+trace+onwards for an example.
* 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.
* On the subject of performance and simplicity, no need for an actual garbage
collector, reference counting is enough because you cannot make circular
references.
* Modifying the procedure arguments is done via `upvar`: in Tcl, a variable
reference is just a name (string) with a stack frame number, quite elegant
considering the language's 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 use the very convenient tclreadline, tdom,
pipethread and tclcurl.
Some more here: https://core.tcl-lang.org/jenglish/gutter/
* Channels is 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 a channel without an actual backing
FD. Basically like glibc's unportable fopencookie.
* Centralize all ioctl/fcntl shit and even more (like defining the EOF char).
* Integration with the event loop via `chan event` 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.
* An elegant thread extension consisting of an interpreter per thread and no
raw access to other thread's memory. Comes with both simple (`thread`) 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.
* `uplevel` (execute 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. Basically
CL macros, but different (less powerful than CL's synergy between "naked AST"
style homoiconicity, symbols as first-class objects and quasi-quoting, but
not seen as different from functions, that you can't pass to map in CL).
* Safe interpreters let you do very fun things like config files in Tcl with
limited access to the machine and master interpreter.
* Obvious Lisp inspiration:
* Homoiconic through strings
* Usual FP goodies like map/filter/apply
* Already mentioned macros
* Proper prefix arithmetic allowing for `* 4 [+ 1 2 3]` instead of
`expr {(1 + 2 + 3) * 4}` with sane behaviour for more than two (reduce) or
zero (neutral element) arguments.
* Multiple more-or-less powerful object systems ([incr Tcl] for C++ style OO,
XoTcl for CLOS inspired OO or Snit for something Tk oriented).
* All of that with the same advantage of CL: it does not enforce nor preach a
particular way of programming, unlike the ML family that comes with the
"everything is immutable" ball and chain that often gets in the way instead
of helping (because, big surprise, modifying data is often an essential
part of efficient and intuitive algorithms while recursing only makes sense
when manipulating recursively defined data types).
See https://wiki.tcl-lang.org/page/Functional+Programming for more.
* Biggest inconvenient is the near-death state of the language and community
(practical consequences: no LSP/SLIME equivalent, bugs accumulating, lack of
maintainted libraries) as well as some warts that can't be solved easily.
As someone who knows a bit of CL, the language itself is less powerful
(especially on the macro side) but the standard library is miles ahead.
Basically, a mix of CL and sh that somehow managed to end up very good and
getting even better with time.
I could continue all day, but you should just try it. Some more talk about it:
* https://wiki.tcl-lang.org/page/What+is+Tcl
* https://wiki.tcl-lang.org/page/Tcl+Articles
* https://colin-macleod.blogspot.com/2020/10/why-im-tcl-ish.html
* https://yosefk.com/blog/i-cant-believe-im-praising-tcl.html
* http://antirez.com/articoli/tclmisunderstood.html
Where to begin:
* man n Tcl (or `man 3tcl Tcl` on retarded distros like Debian)
* https://wiki.tcl-lang.org/page/TCL+for+beginners
* https://wiki.tcl-lang.org/page/Tcl+Tutorial+Lesson+0
* https://wiki.tcl-lang.org/ for everything, this is where the Tcl community lives
* Rosetta Code for examples/exercises