Here. Extremely enjoyable to code in and easy to integrate with C which makes integrating with arbitrary libraries and syscalls simple. The language rules are strict, but there are few of them, and they allow for surprising customizability (read: DSL). In a nutshell (for me), as competent as any language, and more enjoyable than most.
This describes explicit use, outside of cases where you may be using it directly or indirectly and not realize, like Expect, or in your network routers like your F5 iRules, etc.
My work is currently specifically Tcl-focused, at ActiveState, but see my other comments for years of enthusiastic Tcl experience from "general" development and operations gigs. I use it where I can, and I can use it in a lot of places.
I've not done any Lua but my oldest son has and he showed me. It really did not stand-out in my mind compared to say python. I guess it's pretty simple, embeddable, interoperable with C. It really was a great first language for him really but so would have js really.
Tcl is pretty neat though. It has this feel like lisp and very simple rules plus everything can be a string, which is prefect for gluing text output together between tools.
I've done a lot of Tcl work; two successive companies I worked at used it as their embedded language. It has its charms, but I would have a hard time working at another company that in 2015 chose Tcl over Lua.
Issues I have with Tcl:
* The syntax is as idiosyncratic as a Lisp, but has few of the advantages that Lisps get for homoiconicity.
* uplevel/upvar is a janky way to get metaprogramming. Compare metaprogramming in Tcl to that of Japanese Tcl errr Ruby.
* The Tcl runtime is outmoded.
I could probably think of others.
There's also the fact that Tcl's vaunted integration with C code has pretty much become par for the course in high level languages. I didn't find writing Ruby extensions to be any more painful than writing Tcl extensions. Modern high level languages also expose full-featured FFIs, so you often don't even need bindings.
Tcl was ahead of its time! It was a good embedded high level language before virtually every large project recognized the need for embedded languages. And the event-based model that Tk forced on it turned out to be pretty useful for network servers. It was a great choice in the late 1990s.
Good points, I'd moved to python for embedding and shimming myself and then got bit cause SWIG had forced Cpython when there were other options later. I do still very much like the simple syntax though.
#!/bin/sh
# the next line restarts using tcl \
exec tcl "$0" "$@"
...
I just go so annoyed with is it /usr/bin/perl or /usr/local/bin/perl or ... And is it awk or nawk or ... And somebody told me this trick with Tcl and I was like, "I'll just use it for this simple script and be done with it."
That is exactly how I think of Lua. Lua stole Tcl's thunder and added its own. Perhaps the only thing missing is a community wide standard macro system that works with Luajit, without that Tcl can still do an one up on Lua with its uplevel.
Given that it has had a better multithreading model compared to Cpython, JavaScript, has been and is a breeze to extend and embed, comes with lambda and coroutines too..
So why not. Very few other languages give a comparable sense of playfulness
Very few other languages give a comparable sense of playfulness
There's an argument that modern software used in production environments shouldn't be imbued with a sense of playfulness just because it's fun.
If your choice is between tcl and Python, use Python. If your situation is "I can use waterer I want, tcl sounds fun," still use Python. Nobody wants to maintain sprawling tcl code today, much less in the future after projects get abandoned by their original creators.
> There's an argument that modern software used in production environments shouldn't be imbued with a sense of playfulness just because it's fun.
Your point is a good one (applicable to any language or technology), but in defense of the OP, bringing fun doesn't preclude usefulness or power. A painful development process doesn't mean "serious software". Additionally, if you don't want to put Tcl in production per se, it can still be part of the development process in a prototyping capacity. It's got great UI facilities (CLI, sockets, GUI), great introspection, and a healthy amount of whip-it-up-atude to get meaningful results quickly (and yes, enjoyably).
Tcl programs are still far easier to distribute (using Tclkit & Starkits / Starpacks) than for Python, which as far as I can tell requires either an installer or the end user to install a distribution of Python.
This one capability puts Tcl in a class that is fairly unique among scripting languages. It gets it into the class of easily distributable languages that usually only includes compiled native binaries like Go, C, C++, Haskell, Ocaml, etc
EDIT: Thinking further, perhaps Node compiled statically and Lua may offer similar capabilities to Tcl in terms of being reasonably distributable. Maybe PHP also if you distribute the static cgi binary.
I guess it's mostly Python, Ruby, Java, C# and Perl that require a distribution to be installed for programs to be easily run. This is mostly a problem for distributing one-off utilities for someone else to run rather than either major applications where an installer wouldn't be comparatively a lot of extra work, or situations where the computers are all under the programmers control.
Perl and python both have wrapper style single exe packaging options. I guess they might not be easy on the dev side, but they are transparent to the end user.
I actually agree with you wholeheartedly (digression: except maybe I will not go with Python as my goto language all the time, and I am pretty sure that's not the argument you wanted to make, but just for the record).
Not all code I write is even intended for production environments, that's where my previous comment was coming from.
Yes. An ncurses-based appliance configuration UI and a seccomp-sandboxed DSL environment.
libtcl is really easy to sandbox with seccomp, I recommend it over [interp create -safe]. Run the interpreter in a seccomp-enabled child and have the parent do all privileged operations. Set resource limits on the child. Have them communicate over a socketpair. Have the parent spawn sandboxed children whenever the rlimits run out. For what we're using it for, it works really nice.
Yes I use it to script telneting into many dinky devices and changing/viewing config all in one fell swoop with expect. I also have some simple tcl/tk scripts to automate some tasks. But most often I do vxWorks dev from the commandline instead of tornado/workbench with the use of tcl scripts that use the WRS provided tcl scripts.
Totally, in business critical systems for all sorts of stuff.
Rewriting it would be enormous effort and provide no business benefit and be full or risk of introducing new (or re-introducing old) bugs in the process of converting to some whiz-bang c# or whatever is trendy.
We even built custom integration modules (DLLs in Visual C++ 6 for anyone curious). They integrate to legacy AS/400 systems and the interfaces used are totally legacy and unlikely to be easy to integrate with c++ 2015.
So, we're absolutely still using Tcl (and Tk) in 2015 and it is still relevant. It will be in use until the company (or the sun) implodes.
I do hate the syntax though. Yuk. [edit: I see others commenting that that's the thing they like ! I'm obviously an outlier or our code sucks more than most.]
It's the main scripting language in the Cloverleaf interface engine. One of the bigger player in the healthcare systems integration arena (along with Mirth, Corepoint and a few more.)
Depends.
Lets say you have a service that is running on your local PC at some port >1024. It uses a special binary TCP protocol and controls hardware from which images are coming in live stream. You want to display these images in a browser window, on the way there you want to resize them. And then you want to use them in the web application where the window is embedded. You have a stable tested Tcl library to do this in normal client environments, but now the requirement is a web application.
How would you get Javascript and emscripten to do this task?
I think there are two points, where a browser plugin is still relevant: (1) connect with hardware or resources where a browser has no access, from a web page. That is when you can write a little companion Tclet to do exactly this little task. (2) Deployment of an existing Tcl application to thousands of users. That's so much easier when you just need to drop the .tcl file on a web server, and your users get the update as soon as they press F5 in their browser to reload the page.
As it stands, Tcl is still relevant in 2015. It is for example used as a scripting language in hardware design toolchains (such as ModelSim and Xilinx ISE).
Furthermore, the "standard" Git tools "gitk" and "git gui" are written in Tcl.
Lots of places the "full stack" developer will never see. CAD and simulation software, routers, electronics, 3d graphics, industrial control. The web is still only a small corner of the software world.
I've actually used it a lot as a sort of "sane" scripting engine that I could include with other software to deal with various configuration tasks that would be too painful in DOS batch or (somewhat less painfully) bash.
So it has gotten used a lot around the edges of other software that I've written in C# or as part of config steps in InnoSetup.
It's a great tool for random little messy bits that need to be done where you don't want to deal with installing something larger.
Interresting project :). Every project in this direction is thriving and fun, no doubt. I am happy to see these developments, hopefully they go on!
The browser plugin on the other side is mature and fits in where EmTcl, NaTcl etc. leave off: when it comes to use the full feature set of Tcl and its huge extension library, including Tk windows, in the browser and in production code. Intranet web applications maybe, e.g for the use cases I mentioned above. Therefore it still has its niche, I think.
But maybe it will be possible to do things like sockets on arbitrary ports with arbitrary protocols, or driving external hardware, with EmTcl in the future? That would be great :-)!
This is great! I remember the slide rule I wrote in Tcl/Tk in 1997 was able to run in the browser plugin: http://canonical.org/~kragen/slide-rule.tcl. I wonder if it still does!
The Tcl plugin could have been an awesome alternative to Java applets. Too bad they abandoned it.
Unlike others here, I don't think Tcl is "extremely enjoyable to code in", largely due to its lack of first-class aggregate data structures, but it makes doing simple things very simple.
I don't know when you last worked with Tcl, but it's got lists (as always), dictionaries, and integrated first-class object system (after years of various extensions). Also, if it's an option, punting structures to C can be nice to organize data.
Re: abandoned applets - some see that as dodging a bullet. If it became a Big Deal in the browser, it arguably could have cemented itself into the form it had at that time, because of maintaining compatibility for that audience. It's a thought exercise I haven't completely thought through, to be honest, which just occurred to me because Tcl has done a tremendous job being true to itself anyway, and has a great amount of compatibility with historic versions of itself.
> punting structures to C can be nice to organize data
I'm a Tcl fan, but the above is actually somewhat problematic, because to hold a reference to the C struct, you have to then manually free it later, losing some of the benefits of a language with automatic memory management.
Real dicts, and the new object stuff are big improvements though.
> ...the above is actually somewhat problematic, because to hold a reference to the C struct, you have to then manually free it later, losing some of the benefits of a language with automatic memory management.
I usually frame the data as clientData passed to a managing command (i.e. custom built first-class command), with appropriate allocation/deallocation. As often as not, I'm creating two commands: an anonymous reference template, and a command-creating-command that will instantiate instances of the "anonymous reference template". Then I can create an arbitrary number of arbitrarily named commands that pack and process their data, including freeing on destruction.
To the uninitiated, this sounds like object-oriented programming, which is arguably true, but doesn't automatically come with subclassing, inheritance, etc, etc. Tcl does have first class objects, but what I'm describing here isn't them.
FlightAware has released the SpeedTables package for Tcl, which basically creates C structures on the fly, as well as C-based accessor routines:
"Speed tables reads a structure definition and emits C code to create and manipulate tables of rows of that structure. This allows operations to be performed on the table at native code speeds, using a custom extension that manages rows of fields as native C structs and emit subroutines for manipulating those rows in an efficient manner."
FlightAware.com deals with extremely high-volume data throughput, and they manage the whole process with Tcl.
It pretty much is cemented into the form it had at that time. My 1997 code runs in current Tcl/Tk, although I had at some point broken it by adding a #comment without a semicolon before it, but that was never valid. I think Tcl introduced some incompatibilities around 1992 or 1993, since the old icb client I used, which embedded an early version of Tcl from around that time, had some incompatibilities with scripts written in Tcl 4.
1997 is probably pretty close to the last time I worked with Tcl.
Tcl lists and arrays (dictionaries) are great, but arrays aren't first-class; you can't pass them as arguments or return them from expressions, only store them in variables. I'd argue that TclOO objects aren't first-class either: you don't have to explicitly destroy strings or lists (which are strings!) or even arrays when you're done with them, but you do have to explicitly destroy TclOO objects, just like Tk widgets.
I don't mean to imply that the object-graph memory model used by Lisp, Python, Perl 5, Java, ML, and Ruby has no disadvantages compared to the flatter memory model used by Tcl, Perl 4, and awk. But usually, for the things I do in low-performance interpreters, the disadvantages of the object-graph memory model are less compelling than the advantages. (I have some draft notes on this at http://canonical.org/~kragen/memory-models, if you're interested.)
Would be nice if there was some kind of walkthrough. Nothing shows what kind of tags are needed in HTML, what kind of files are uploaded to the web server, how to interact with the DOM, ect, ect.
Tcl is an awesome language for developing cross-platform desktop apps in, and Tk bindings are everywhere. I use Tk as the foundation for Mac (and soon Windows) apps written in Python and Perl as well as Tcl.
52 comments
[ 2.7 ms ] story [ 104 ms ] threadThis describes explicit use, outside of cases where you may be using it directly or indirectly and not realize, like Expect, or in your network routers like your F5 iRules, etc.
My work is currently specifically Tcl-focused, at ActiveState, but see my other comments for years of enthusiastic Tcl experience from "general" development and operations gigs. I use it where I can, and I can use it in a lot of places.
This is definitely a sweet-spot for TCL. It's not surprising that TCL doesn't get more attention when this use case has been so stable for so long.
Tcl is pretty neat though. It has this feel like lisp and very simple rules plus everything can be a string, which is prefect for gluing text output together between tools.
Issues I have with Tcl:
* The syntax is as idiosyncratic as a Lisp, but has few of the advantages that Lisps get for homoiconicity.
* uplevel/upvar is a janky way to get metaprogramming. Compare metaprogramming in Tcl to that of Japanese Tcl errr Ruby.
* The Tcl runtime is outmoded.
I could probably think of others.
There's also the fact that Tcl's vaunted integration with C code has pretty much become par for the course in high level languages. I didn't find writing Ruby extensions to be any more painful than writing Tcl extensions. Modern high level languages also expose full-featured FFIs, so you often don't even need bindings.
Tcl was ahead of its time! It was a good embedded high level language before virtually every large project recognized the need for embedded languages. And the event-based model that Tk forced on it turned out to be pretty useful for network servers. It was a great choice in the late 1990s.
Can you really make arbitrary syscalls directly from Tcl? That sounds interesting to say the least
There's an argument that modern software used in production environments shouldn't be imbued with a sense of playfulness just because it's fun.
If your choice is between tcl and Python, use Python. If your situation is "I can use waterer I want, tcl sounds fun," still use Python. Nobody wants to maintain sprawling tcl code today, much less in the future after projects get abandoned by their original creators.
Your point is a good one (applicable to any language or technology), but in defense of the OP, bringing fun doesn't preclude usefulness or power. A painful development process doesn't mean "serious software". Additionally, if you don't want to put Tcl in production per se, it can still be part of the development process in a prototyping capacity. It's got great UI facilities (CLI, sockets, GUI), great introspection, and a healthy amount of whip-it-up-atude to get meaningful results quickly (and yes, enjoyably).
This one capability puts Tcl in a class that is fairly unique among scripting languages. It gets it into the class of easily distributable languages that usually only includes compiled native binaries like Go, C, C++, Haskell, Ocaml, etc
EDIT: Thinking further, perhaps Node compiled statically and Lua may offer similar capabilities to Tcl in terms of being reasonably distributable. Maybe PHP also if you distribute the static cgi binary.
I guess it's mostly Python, Ruby, Java, C# and Perl that require a distribution to be installed for programs to be easily run. This is mostly a problem for distributing one-off utilities for someone else to run rather than either major applications where an installer wouldn't be comparatively a lot of extra work, or situations where the computers are all under the programmers control.
Not all code I write is even intended for production environments, that's where my previous comment was coming from.
libtcl is really easy to sandbox with seccomp, I recommend it over [interp create -safe]. Run the interpreter in a seccomp-enabled child and have the parent do all privileged operations. Set resource limits on the child. Have them communicate over a socketpair. Have the parent spawn sandboxed children whenever the rlimits run out. For what we're using it for, it works really nice.
See http://wiki.tcl.tk/1502 for descriptions, reactions, and links.
Caius – A functional testing framework in object-oriented Tcl
http://caiusproject.com/
https://github.com/tobijk/caius
Rewriting it would be enormous effort and provide no business benefit and be full or risk of introducing new (or re-introducing old) bugs in the process of converting to some whiz-bang c# or whatever is trendy.
We even built custom integration modules (DLLs in Visual C++ 6 for anyone curious). They integrate to legacy AS/400 systems and the interfaces used are totally legacy and unlikely to be easy to integrate with c++ 2015.
So, we're absolutely still using Tcl (and Tk) in 2015 and it is still relevant. It will be in use until the company (or the sun) implodes.
I do hate the syntax though. Yuk. [edit: I see others commenting that that's the thing they like ! I'm obviously an outlier or our code sucks more than most.]
https://trac.macports.org/wiki/FAQ#whytcl
I think there are two points, where a browser plugin is still relevant: (1) connect with hardware or resources where a browser has no access, from a web page. That is when you can write a little companion Tclet to do exactly this little task. (2) Deployment of an existing Tcl application to thousands of users. That's so much easier when you just need to drop the .tcl file on a web server, and your users get the update as soon as they press F5 in their browser to reload the page.
Furthermore, the "standard" Git tools "gitk" and "git gui" are written in Tcl.
So it has gotten used a lot around the edges of other software that I've written in C# or as part of config steps in InnoSetup.
It's a great tool for random little messy bits that need to be done where you don't want to deal with installing something larger.
http://aidanhs.github.io/emtcl/
The browser plugin on the other side is mature and fits in where EmTcl, NaTcl etc. leave off: when it comes to use the full feature set of Tcl and its huge extension library, including Tk windows, in the browser and in production code. Intranet web applications maybe, e.g for the use cases I mentioned above. Therefore it still has its niche, I think.
But maybe it will be possible to do things like sockets on arbitrary ports with arbitrary protocols, or driving external hardware, with EmTcl in the future? That would be great :-)!
The Tcl plugin could have been an awesome alternative to Java applets. Too bad they abandoned it.
Unlike others here, I don't think Tcl is "extremely enjoyable to code in", largely due to its lack of first-class aggregate data structures, but it makes doing simple things very simple.
Re: abandoned applets - some see that as dodging a bullet. If it became a Big Deal in the browser, it arguably could have cemented itself into the form it had at that time, because of maintaining compatibility for that audience. It's a thought exercise I haven't completely thought through, to be honest, which just occurred to me because Tcl has done a tremendous job being true to itself anyway, and has a great amount of compatibility with historic versions of itself.
Anyway, now I'm off to look at slide rules ;)
I'm a Tcl fan, but the above is actually somewhat problematic, because to hold a reference to the C struct, you have to then manually free it later, losing some of the benefits of a language with automatic memory management.
Real dicts, and the new object stuff are big improvements though.
I usually frame the data as clientData passed to a managing command (i.e. custom built first-class command), with appropriate allocation/deallocation. As often as not, I'm creating two commands: an anonymous reference template, and a command-creating-command that will instantiate instances of the "anonymous reference template". Then I can create an arbitrary number of arbitrarily named commands that pack and process their data, including freeing on destruction.
To the uninitiated, this sounds like object-oriented programming, which is arguably true, but doesn't automatically come with subclassing, inheritance, etc, etc. Tcl does have first class objects, but what I'm describing here isn't them.
"Speed tables reads a structure definition and emits C code to create and manipulate tables of rows of that structure. This allows operations to be performed on the table at native code speeds, using a custom extension that manages rows of fields as native C structs and emit subroutines for manipulating those rows in an efficient manner."
FlightAware.com deals with extremely high-volume data throughput, and they manage the whole process with Tcl.
https://github.com/flightaware/speedtables
1997 is probably pretty close to the last time I worked with Tcl.
Tcl lists and arrays (dictionaries) are great, but arrays aren't first-class; you can't pass them as arguments or return them from expressions, only store them in variables. I'd argue that TclOO objects aren't first-class either: you don't have to explicitly destroy strings or lists (which are strings!) or even arrays when you're done with them, but you do have to explicitly destroy TclOO objects, just like Tk widgets.
I don't mean to imply that the object-graph memory model used by Lisp, Python, Perl 5, Java, ML, and Ruby has no disadvantages compared to the flatter memory model used by Tcl, Perl 4, and awk. But usually, for the things I do in low-performance interpreters, the disadvantages of the object-graph memory model are less compelling than the advantages. (I have some draft notes on this at http://canonical.org/~kragen/memory-models, if you're interested.)
I hope you enjoy the slide rule :)
I forgot about arrays, tbh. I personally don't like the "feel" of them. The dictionaries I was referring to are these guys: https://www.tcl.tk/man/tcl/TclCmd/dict.htm
Nice to hear your thoughts on the matter, though.
Cheers.