
Tcl: Everything Is a String - blacksqr
https://wiki.tcl-lang.org/page/everything+is+a+string
======
nrclark
Heart️ for Tcl.

Tcl wasn't my first language, but it's near and dear to my heart. It's a
little oddball for sure.

I can't decide whether it's Python trying to be Bash, or Bash trying to be
Python. But it's surprisingly expressive.

Everything is strange about the syntax - from "everything is a string" to
"expr" to the weird variable-assignment syntax.

It's also really tiny, and has a great async event-loop framework. It has
built-in support for sockets and non-blocking I/O. It has a GUI toolkit that's
pretty useful for making quick-and-dirty tools. It's incredibly easy to use
interactively with a REPL. And it's still the scripting language of choice for
the FPGA industry, which is where I got my start as a software engineer.

The Tcl community is small and stable. And the language just keeps soldiering
onwards, in a gradual way. It feels like it's been stable and fully-realized
for the last 20 years. No breaking API changes, no syntax changes. It just
keeps on keeping on, providing automation to tools that need it. Tcl has
outlived a bunch of newer languages, and I hope it sticks around for another
20 years.

~~~
pjc50
Tcl/Tk was a _tremendous_ rapid GUI prototyping tool. I remember cobbling
together a Verilog schematic viewer in a couple of weeks using that
combination, for the Series A funding round of the startup I was working at in
the early 2000s.

~~~
abhgh
This was my reason for foraying into Tcl too. Till then I had used Java's AWT
and Swing; but prototyping with Tcl/Tk was _way_ faster and intuitive.
Mid-2000s. I ended up liking the language - idiosyncratic as it was. Partly
the reason I am curious about and planning to read Ousterhout's (creator of
Tcl) book "A Philosophy of software Design" soon.

~~~
senderista
It’s a great book (only one reference to Tcl that I recall though). Also
Perl/Tk was the first GUI toolkit I used (followed by Glade).

------
kroger
A nice article to quickly understand Tcl defining features is "Tcl the
Misunderstood":
[http://antirez.com/articoli/tclmisunderstood.html](http://antirez.com/articoli/tclmisunderstood.html)

And some previous HN discussion on the article:

[https://news.ycombinator.com/item?id=7069642](https://news.ycombinator.com/item?id=7069642)

[https://news.ycombinator.com/item?id=4920831](https://news.ycombinator.com/item?id=4920831)

Edit: grammar

------
crispyambulance
My favorite thing in the Tcl ecosystem was "Expect". It's a tool you can use
to automate ssh/telnet/serial connections to other machines.

It has a really mature and elegant way of handling the automation of
command/response scenarios in connections to other machines.

I do similar stuff with .net now, but it's not as pretty. I wish there were a
modern equivalent of Expect that as as nice.

~~~
dharmab
Expect is an amazing tool for dealing with old hardware that _insists_ on
interactive prompts instead of CLI flags.

~~~
rikkus
And modern software that does the same. Cisco AnyConnect VPN thing, for
example. You can feed it a command file, but that doesn’t give you any error
handling or logic to handle dynamic responses. Expect to the rescue!

------
winrid
Redis was originally in Tcl!

[https://gist.github.com/antirez/6ca04dd191bdb82aad9fb241013e...](https://gist.github.com/antirez/6ca04dd191bdb82aad9fb241013e88a8)

~~~
derefr
And SQLite was originally a TCL extension!

From
[https://www.sqlite.org/tclsqlite.html](https://www.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.

Given both of these, it kind of feels like something about the Tcl philosophy
leads people to build (or draws in the sort of person who builds)
simple/elegant data storage layers. Makes me more curious about it.

~~~
lanstin
Ousterhout's book on Tcl has a chapter one that is essentially "How to do
small reusable things in unix and win" \- it's absolutely brilliant and
explains how to think in unix and why composable entities with simple
interfaces have done so well. SQLite and TCL are the best of unix philosophy
made concrete. I just read in this thread that he expanded it to an entire
book - I'll be reading that as soon as I finish binging The Family Man on
Prime Video. Extending TCL with a new C command is exactly as hard as a CS 101
C program (which at the time was the lower limit on easy for CS folk).

------
bachmeier
This paper by John Ousterhout (creator of Tcl) is a good read if you think Tcl
is a weird language plagued by bad design decisions. If that describes you,
it's probably the case that you don't understand the problem Tcl was designed
to solve.

[https://web.stanford.edu/~ouster/cgi-bin/papers/tcl-
usenix.p...](https://web.stanford.edu/~ouster/cgi-bin/papers/tcl-usenix.pdf)

~~~
bloaf
>Almost all Tcl ‘‘programs’’ will be short, many only one line long.

I weep silently over the 50kloc tcl codebase I help maintain.

------
nerpderp82
Tcl is an alien technology I wish I embraced when I was first exposed to it. I
didn't quite get it, I was confused, so I gravitated towards Perl because it
reminded me of C somewhat. I wasn't aware of my cognitive blind spots. In many
ways Tcl is more powerful than most implementations of Lisp. Like a Lisp
crossed with a Forth with the ability to turn spheres inside out with no
tearing during execution. Magic.

~~~
pmoriarty
_" In many ways Tcl is more powerful than most implementations of Lisp."_

Could you elaborate on this? In what ways is it more powerful?

Also, I don't get what connection TCL has with Forth. They seem uttery
different from each other to me.

~~~
ithkuil
One thing those three languages have in common is that they are almost syntax-
less. Each, in its own particular way, allows user defined code to process
tokens of the program source before it gets to the core interpreter, allowing
users to implement custom control structures and DSLs.

~~~
stjohnswarts
I've seen a lot of people compare it to Forth for DSL implementation

------
davidw
I think the article doesn't make enough mention of the fact that internally,
most things are not actually strings for much of their lifetime. They must be
able to be represented that way, but that's different than everything being a
string all the time. It does create a few problems, but they're a bit more
subtle than "OMG, the integers are strings all the time!"

~~~
kevin_thibedeau
This is an old wiki entry that dates from the pre-8.0 days of Tcl (The history
is truncated). For the past 20 years everything has been _representable_ as a
string.

~~~
blacksqr
It is old, but continuously updated. Last update, last Friday.

~~~
kevin_thibedeau
That is irrelevant when the main thrust of the article is outdated and
reflects the worldview from before Tcl_Obj was added.

------
pjmlp
Actually since Tcl 8 that is no longer true, yet it keeps being repeated as
such.

[http://www.tcl.tk/software/tcltk/8.0.html](http://www.tcl.tk/software/tcltk/8.0.html)

TclTk was great, but it also teached me never again to rely on languages
without JIT or AOT available on their toolchains.

Rewriting Tcl functions into C code was a routine task.

~~~
takeda
Yeah, but that just changed internally, in the language everything is still a
string.

~~~
wrenky
A better way to phrase it (..even before tcl 8) is that everything can be
TREATED like a string.

Numbers arent being converted to and from strings, things like sockets/files
arent strings (their handles are though!)

~~~
_ph_
Right. I think the one great feature it shapes with Lisp is, that everything
has a textual representation. That means, all types of values can be presented
as text and can be recreated from a textual representation. For Lisp, it is
S-Expressions, which can be printed and read, for TCL it is the syntax which
can be printed as strings and interpreting strings as data.

~~~
dmux
>I think the one great feature it shapes with Lisp is, that everything has a
textual representation.

Is this true even for procedures? I was recently playing around with Scheme
and was disappointed that once a procedure is defined, it got internalized and
didn't have a textual representation other than #<proc> or the like.

In TCL, procedure signatures and bodies are stored within the runtime. You
could essentially dump the entire state to a TCL file.

------
jascii
For me Tcl's killer app has been Expect: [https://core.tcl-
lang.org/expect/index](https://core.tcl-lang.org/expect/index) there is
nothing quite like it if you have to manage 1000's of devices and cli's are
the only thing you have to do it!

~~~
stjohnswarts
have you used pexpect?

------
geogra4
My first job was in Tcl. I grew to really like the language, though when I had
to leave the company I was at a pretty strong disadvantage due to how uncommon
it is.

Everything is a string is a great way to reduce the mental load about typing.

~~~
commandlinefan
One of my earlier jobs was porting Travelocity.com from TCL to Java - the TCL
programmers loved the old site and absolutely hated the "new" one. I don't
think I've ever managed to make more enemies in my professional life than I
did in those couple of years.

~~~
geogra4
Tcl to Java is a huge change. Totally different syntax / syntactic style. I
can imagine the annoyance of the Tcl programmers having to deal with the
inherant verbose-ness of java.

~~~
commandlinefan
Yeah, and this was in the relatively early days of Java, too, so the front-end
was all JSP. Oh, did I mention they originally gave us a three-month deadline
to port the ENTIRE site?

------
elamje
The SQLite author is a big Tcl user. I believe the codebase is primarily Tcl
when you include the test suite, though the core implementation is obviously a
C library.

D Richard Hipp is his name and he has some nice talks online. He uses his own
text editor and chat app he wrote in Tcl to maintain the project and
communicate with other developers.

~~~
catalogia
From what I understand, D Richard Hipp's appreciation of Tcl is the reason
SQLite has dynamic typing. (I believe I heard this in one of his talks that's
on youtube, which are excellent.)

~~~
elamje
That makes sense. I heard him say that the pain points of dynamic typing are
mostly just people using it for web apps that eventually have to migrate to
Postgres and the like, causing some headaches because client server DB’s are
much more rigid, causing errors.

I agree that his talks are great! He’s such an enthusiastic guy.

I hope SQLite will adopt default foreign keys and WAL sometime soon, but I
understand that he needs to keep it as backwards compatible as possible.

------
pinewurst
Don't forget the amazing AOLserver, which was a very elegant web applications
server with Tcl as the native template language. This was a great environment.

~~~
gnachman
I was tech lead for it for a couple years. Glad someone remembers it :)

~~~
lanstin
Hey! I wrote flap in TCL module for it! Loved using AOLserver but writing the
extension taught me to fear threads - now loving Golang :) but I miss AOL,
AOLserver, SAPI and TCL in the evenings.

------
gilbetron
I have about 5 years of heavy experience with TCL, split in half by 15 years
away from it. I got a lot done with it, and it is an interesting language, but
I have never, ever said, "I wish I was using TCL" in any situation. It is a
unique journey down an alternate path for computer languages, that really ends
up nowhere compelling, but the path itself is not arduous, although the bugs
can be.

~~~
fluffything
I had 1 year of full-time experience with TCL, and I can basically summarize
it in the same way as you: got a lot done with it, wasn't horrible, but don't
miss it.

In retrospect, I am kind of happy that somebody actually went and built TCL.
"Everything is a string" is not really a sound PL paradigm, but someone needed
to get stuff done, and it worked quite fine for that. It's super simple and
super powerful, and beginners can be productive with it really quickly.

------
eesmith
> This simple and unified perspective on type is fundamental to the design of
> Tcl, and puts it in an exclusive category programming languages that do not
> have at least two data types that can be distinguished. The other languages
> in this category are forth, BCPL, and assembly language.

What about TRAC?
[https://en.wikipedia.org/wiki/TRAC_(programming_language)](https://en.wikipedia.org/wiki/TRAC_\(programming_language\))

------
foobar_
There is an object-oriented extension to Tcl which is along the lines of CLOS.

[http://media.wu-wien.ac.at/whatIsXOTcl.html](http://media.wu-
wien.ac.at/whatIsXOTcl.html)

Lispers need to stop thinking that they are the only ones who can do "macros"
and "DSLs". The evidence is clearly on the contrarian side. You can have
syntax and macros and be practical.

If the failure of Tcl has taught us anything its that performance is
important.

~~~
flavio81
>Lispers need to stop thinking that they are the only ones who can do "macros"
and "DSLs". The evidence is clearly on the contrarian side.

We know that one can do "macros" in many other languages including of course
TCL. The question is how difficult is to do them and how easy is to have
control over there. Lisps, due to code being s-expressions, make macro
creation extremely easy, and Common Lisp has useful tools to ease working with
macros, for example macroexpand, which is integrated into most Lisp IDEs to
easily visualize, in-place within the code, how a macro will expand into, step
by step.

In comparison to that, most languages that do allow macros, make it a
cumbersome, buggy task.

~~~
foobar_
XML, Julia, Rust, Crystal, Forth? support macros too. I was just pointing out
that it can be done without sexp. Yes, the tooling sucks. Grammatical
implementation is less powerful but that seems better than implementing a
grammar ontop of sexps. You get some lexical freedom ontop of pure text that
you don't get implementing grammars on top of sexps, respecting lisps
tokenisation rules.

I wonder how far Lisp would have come if people had taken the source-source
translator approach of js and just implemented an Algol frontend to lisp.
There's plenty of things that Lisp had that are far more useful than just
macros.

I think Tcl is the Unix answer to Lisp. Worse is better somehow evolved into a
Lisp.

~~~
kazinator
> _I wonder how far Lisp would have come if people had taken the source-source
> translator approach of js and just implemented an Algol frontend to lisp._

People did that a number of times over Lisp's history, so Lisp would have come
exactly where it has come.

The first Algol-like front end to Lisp was supposed to be the direct
descendant of Lisp 1, namely Lisp 2. This branch went nowhere. The descendants
of Lisp trace back to Lisp 1.5.

In the early 70's there was something called CGOL. It still exists.

There have been various more recent things in that direction.

And of course, certain contemporary languages are basically sort of Lisp-like
things with Algol bolted on.

Lisp 2:
[https://en.wikipedia.org/wiki/LISP_2](https://en.wikipedia.org/wiki/LISP_2)

Manual with code examples:
[http://www.softwarepreservation.org/projects/LISP/lisp2/Abra...](http://www.softwarepreservation.org/projects/LISP/lisp2/AbrahamsEtAl-
LISP2.pdf)

CGOL: [https://en.wikipedia.org/wiki/CGOL](https://en.wikipedia.org/wiki/CGOL)

------
skybrian
It's nice to guarantee that every value has a string representation. The not-
so-nice part is that you have no static types and therefore no easy way to
guard against mixing up safe and unsafe strings, so security reviewers will
have a hard time. This is a design from before when the dangers of handling
untrusted input as bare strings and doing escape handling all over the
codebase were understood.

------
ahartmetz
Everything is a string in CMake, too. Even lists. Be very afraid of strings
containing the separator character ';'...

------
wanderer2323
The string is a stark data structure and everywhere it is passed there is much
duplication of process. It is a perfect vehicle for hiding information. --
Alan Perlis

~~~
ken
I think Tcl strings aren't exactly what Perlis was talking about. First, the
language knows how they're used, so there's a JIT (or whatever) behind the
scenes eliminating the literal deserialize-process-serialize pattern you see
in shell scripts. Second, a lot of Tcl data types (hash tables, sockets, etc)
can be represented by strings but the string is just a simple reference to a
rich internal structure. It's almost more like a pointer than a string in
other languages.

~~~
lanstin
I know this item is old but surely no shell script should be limited by string
copying of the language? Maybe string shuffling thru pipes, but that's the
reason the CPU briefly spikes.

------
tabtab
I had a bit of trouble knowing which "escape level" I'm in while debugging.
You have strings that wrap strings that wrap strings, etc.

Maybe with more experience I'd learn to manage string nesting levels better,
but there does seem to be a non-trivial learning curve, at least for us
mortals.

------
jadbox
Everything being a string at a language level is similar to the paradigm as
'everything is an object' in java. Outside of select use-cases (scripts/text
proc), the language generally fights against both conciseness and performance.

I worked with UCLA where a few teams needed to use Tcl to maintain existing
web servers, and virtually every developer highly complained about using it
(aside from one or two career Tcl-ers). To be honest, I don't personally have
much experience with Tcl, but from what I've seen/heard, I wouldn't ever think
of building web servers upon it.

~~~
Mountain_Skies
One of my first jobs after college involved creating websites using Vignette
StoryServer. At the time Tcl was the only language you could use with it. I
was happy when a new version was released that supported Java and ASP. Tcl
looked like voodoo magic to me but I'm sure for those who really got it, they
were pretty productive with it.

~~~
kiwidrew
You've brought back some painful memories for me. I'm permanently allergic to
the words "lindex" and "upvar", and cringe whenever I see a "," character in a
URL...

Vignette's only redeeming qualities were that: (1) the page templates
permitted the execution of arbitrary Tcl code, not just the small subset that
was documented by Vignette; and (2) much of the Vignette functionality was
itself actually implemented in Tcl.

This led to the glorious discovery that one could simply _bypass_ the entire
crazy Vignette system and use it like a very expensive (and somewhat slower)
AOLserver. I sometimes feel sorry for the poor souls who inherited my
terrifying and entirely undocumented creation, but that's what happens when
management _forces_ developers to use the entirely wrong tool for the task at
hand. ("We spent $100k USD on this software so we're damn well going to use
it!")

------
monetus
I think it is worth mentioning that I learned TCL through the Pure Data audio
language, which was designed with the idea of continuously supporting at least
20 years of hardware IIRC.

It is such a useful language.

------
neilobremski
I have never used Tcl but this headline truly intrigued me. It sounds like the
antithesis of JavaScript's "everything is an object". An object is very
abstract whereas a string is very ... literal? I know many generic operations
I can already do with a string but then inspecting its contents (which would
be a generic operation) may reveal other capabilities, restrictions, what have
you. Hmm ...

------
FabianBeiner
TCL. That brings me down the memory lane to IRC and all those Eggdrop bot
scripts I've written. :)

------
ycombonator
It still powers some companies with an annual rev ~1B.

------
jsgrahamus1953
For most of the past 38 years I have earned my living as a computer
programmer/developer using the Mumps programming language. It, too, views most
everything as a string (or an array), and sometimes that string can also
function as a number.

------
stevekemp
If you're not familiar with TCL this introduction from redis-author Antirez is
worth a read:

[http://antirez.com/articoli/tclmisunderstood.html](http://antirez.com/articoli/tclmisunderstood.html)

------
RandomGuyDTB
That's really weird. I didn't know this was a thing but I had a dream a couple
days ago that I was using a language in which everything was a string (like
Lisp but with strings instead of lists). Guess I'll have to give it a whirl.

------
jhallenworld
Tcl: one of the slowest languages

[https://github.com/trizen/language-
benchmarks](https://github.com/trizen/language-benchmarks)

~~~
bbmario
wtf luajit is a monster

~~~
tomnipotent
Probably why it's so popular in games as a scripting engine (going back to
2003).

~~~
est
> in games as a scripting engine (going back to 2003)

you are think of lua, luajit is a different beast.

[http://luajit.org/changes.html](http://luajit.org/changes.html)

LuaJIT 1.0.3 — 2005-09-08

This is the first public release of LuaJIT.

~~~
tomnipotent
Didn't realize they had the Python/PyPy thing going on. Thanks for the info!

------
rongenre
Everything is a string including the comments -- commenting code actually
degrades performance!

~~~
mdaniel
This business falls into the "well that's handy" followed by the "who in the
world thought honoring continuation characters in comments was a good idea?!"

    
    
        #! /bin/sh
        # the next line restarts using tclsh \
        exec tclsh "$0" ${1+"$@"}
    

This page is just filled with _wow_ :

[https://wiki.tcl-lang.org/page/comment](https://wiki.tcl-
lang.org/page/comment)

with an especial nod toward:

    
    
        set two [1 + 1] ;# line comment needs a statement terminator

~~~
williadc
One of the world's largest hardware companies uses the line continuation
feature to help make stuff you've almost certainly used today.

Whether that is the best way to solve their problem is another story, but that
feature does get used.

~~~
lanstin
And the nice thing about TCL as a language is there's just like 3 or 4 rules
to remember and then you can embed the parser in your head. # is a command
that discards all its arguments. So it's in the normal flow of syntax, so line
continuation works. It's odd to see but easy to reason about after you are
used to it.

------
nahumba
ha! i 'member this. hmmmmm

Stringly Typed. yes. yes.

[https://blog.codinghorror.com/new-programming-
jargon/](https://blog.codinghorror.com/new-programming-jargon/)

now that you put a duck in news. i call to remove it. thankyou.

------
tyingq
They fixed it later, but in the beginning, everything was a C string. Meaning
you couldn't output a NULL char. Pretty frustrating when I discovered this
while trying to write a length encoded protocol :)

------
derefr
About a decade ago now, I was writing a group chat system of the Slack/Discord
variety, and I was pondering how I'd like to support markup. I wanted to do
something more powerful than just the regular
"bold/emphasis/strikeout/links/etc." set, as the users of this group-chat were
the type who would enjoy adding animations and other "effects" to their text,
especially on top of their custom emoticons/stickers. (Don't fret, this wasn't
team-productivity software ;)

What I ended up doing was extending the backend with support for parsing
messages using a "command language"—essentially Tcl. The "everything is a
string" feature of Tcl-like languages was essential, because I wanted these
"commands" to be arbitrarily composable, and both the input and output were
required to be strings (i.e. HTML), so commands couldn't pass data-structures
to one-another; they had to accept strings, and emit strings.

The user was not allowed to enter arbitrary HTML in their message (this was
filtered out as a pre-filtering step), but any Tcl command was allowed to take
HTML-strings as input and emit HTML-strings as output, and the string that was
eventually generated, HTML and all, was treated as the user's actual message.
Many of the implemented commands would parse the input HTML-string into an
AST, tweak it somehow, and then re-emit it as a string.

An example of such a command would be something like:

    
    
        And then [spoiler the protagonist died [rotate 5 [big :ohno:]]]
    

...where 'rotate' and 'big' layer together CSS effects (combining CSS classes
with a bit of custom element style to parameterize it, with each rewriting the
HTML AST structure of the previous to ensure the CSS effects "stack"
correctly); and 'spoiler' is just a CSS class with pseudo-selector behaviors.

Another example would be:

    
    
       [type oh nooo[sfx fall]oooooooo]
    

...which would use a CSS class+JS trigger to display the message one character
at a time the first time it became viewport-visible... and embed a hidden
<audio> element at the top of the message body, that would get triggered as
the typing progressed to it. Sort of like the dialogue event-scripting in a
video game.

And, of course, just like an IRC bot, you could rely on the backend being
Turing complete, in ways like:

    
    
       # generate random numbers
       [roll 1d6]
    
       # set a countdown timer on a user,
       # resetting it whenever the user talks
       [deadmanswitch 5mins I'm slacking off again!]
    
       # get the backend to (use a job queue to)
       # fetch a resource, plop it into its own download folder,
       # and then post a link to the retrieved copy
       [dl http://example.com] 
    
       # same, but also create a BitTorrent torrent for
       # the file, register it with a BT tracker on
       # the backend, and then emit the URL of the torrent file
       [torrent [dl http://example.com]]
    

\---

At this point, I don't really think there's much room for a new group chat
system; but this one feature was really cool to me, and I always wish I had
seen it implemented in some bigger product.

------
known
In AWK every value is Integer/String

------
m4r35n357
gitk !!!

also Linux kernel config

------
IshKebab
> This is one of the central features of Tcl.

One of the biggest missing features surely? "Everything is a string" is a
terrible design.

~~~
protomyth
Yet UNIX pipes are strings and amazingly popular. Its amazing how we don't see
a movement to get typed streams so we can give up the reparse culture of UNIX.
I guess PowerShell does typing.

~~~
pjc50
The problem with typed streams is that couples the implementations together on
both ends and tends to de-genericise them. You get a "grep" that would _only_
work on strings when actually you'd be quite happy grepping numbers 99% of the
time. Also in order to serialise them you'd need fully typed _files_. Notice
that you can't serialise a Powershell stream.

The world tried "everything is XML" and more recently "everything is JSON" as
a solution to this. The latter is almost there.

~~~
astine
" _Notice that you can 't serialise a Powershell stream._"

Not sure what you mean by this. This code works fine:

    
    
        $credential = Get-Credential -Message "Enter Credential"
        $credential | Export-Clixml "credential.xml"
        $credential = Import-Clixml "credential.xml"
    

You can also

    
    
        $variable | Out-File ./file.txt
    

if you just want to save the text output.

~~~
7thaccount
Yea, but Powershell is nearly unusable in many use cases. It is soooo slow for
some things. I really like bits and pieces of it though.

