Edited by humans. Written by AI. How our editing works
All articles

When Everything Is a String: TCL's Peculiar Design

TCL treats code, data, and types as strings. A developer explores why this 1980s language shaped Redis—and remains deeply weird four decades later.

Bob Reynolds

Written by AI. Bob Reynolds

February 28, 20266 min read
Share:
Motivational quote "Everything is a string" with a stylized leaf logo against a purple-blue gradient background

Photo: Dreams of Code / YouTube

Most programming languages ship with macOS by default because Apple needs them. TCL ships with macOS despite Apple wanting to remove it. That tension—between necessity and obsolescence—captures something essential about this language that almost nobody uses anymore but continues to influence software millions depend on daily.

A developer recounts encountering TCL, or Tool Command Language, in their first finance role. Fresh from learning C++, they found themselves working with a language that treats everything—types, expressions, commands, even control flow—as strings. Not metaphorically. Literally.

"When I say everything in Tickle is a string, I mean quite literally everything," they explain. "This includes things you might expect, such as every type being a string, but it also includes some other things you may not necessarily think of, such as complex data structures and even the syntax of the language itself."

This design choice creates a programming environment unlike anything mainstream developers encounter. It's not that TCL is old—many languages from the 1980s remain current. It's that TCL's fundamental architecture diverges so sharply from conventional design that learning it requires unlearning assumptions that feel universal.

The Two Faces of Strings

TCL uses both quotation marks and braces to define strings. The distinction matters enormously. Quotes trigger variable substitution—"$name" becomes whatever value name holds. Braces preserve literal text—{$name} stays exactly as written.

This isn't syntactic sugar. It's the mechanism that controls when code executes. A while loop defined with quotes evaluates its condition once, substituting variables immediately. The same loop with braces re-evaluates each iteration. The difference between an infinite loop and working code comes down to which delimiter you choose.

The developer demonstrates this with a simple counter loop. Using quotes for the conditional expression freezes the tested value at zero. The loop never terminates because it's not actually checking the variable—it's checking the string "0" that replaced the variable when the parser first encountered it. Switch to braces and the code works as intended.

For programmers accustomed to syntax being syntax and data being data, this feels upside-down. The choice between braces and quotes isn't about formatting or readability. It's about execution timing. The same string, delimited differently, produces entirely different program behavior.

Commands Masquerading as Statements

TCL has no statements. What looks like an if statement is actually a command that takes two string arguments: a boolean expression and code to execute if true. What looks like a function definition is the proc command consuming strings that describe parameters and implementation.

This means you can store an if command in a variable. You can store the code that the if evaluates in another variable. Then you can execute both dynamically using eval. The line between code and data doesn't blur—it doesn't exist.

"Everything in tickle is a string. I really cannot stress that enough. This also includes commands such as the eval command itself," the developer emphasizes.

This design enables metaprogramming so powerful it circles back to dangerous. Functions become strings that can be inspected, modified, and executed at runtime. The entire language surface area becomes programmable because the language itself is just structured text.

Redis creator Salvatore Sanfilippo saw this design and recognized something valuable. The first version of Redis—originally called LMDB—was written in TCL. The command structure, the way data types are represented, the string-centric design philosophy: all inherited from TCL. When Sanfilippo rewrote Redis in C, he kept the conceptual model.

Data Structures Built from Whitespace

Lists in TCL are strings with elements separated by spaces. Dictionaries are strings with alternating keys and values separated by spaces. There's no list type or dictionary type—just conventions for how to structure strings and commands for operating on those conventions.

To create a list element containing a space, you nest delimiters. Quote a string inside braces, or use the list command to handle the delimiter dance automatically. Lists can contain lists because a properly delimited substring is just another space-separated structure.

This approach seems fragile until you notice it's also extraordinarily flexible. Adding a new data structure doesn't require modifying the language—just defining new conventions for string interpretation and commands for manipulating them. The language doesn't need to know about your data structures. You teach it by writing commands that understand your conventions.

Modern developers might call this "stringly typed" as a pejorative. But TCL predates that criticism by decades and doesn't apologize. The string-centrism is the point, not a compromise.

Explicit Scope in a World of Conventions

Most languages infer scope from context. Variables defined inside functions stay local unless explicitly exported. Global variables are accessible everywhere unless shadowed. TCL reverses this.

Define a global variable, then reference it inside a function. The code fails. TCL doesn't assume you want global access just because you used a global variable. You must explicitly declare global x inside the function to link the names.

The same applies to reference semantics. Passing a variable to a function passes a copy. To modify the original, you use upvar to explicitly bind a local name to a calling-scope variable. The developer notes: "We've explicitly defined the scope of X to be passed in by reference."

This explicitness violates decades of language design evolution toward implicit behavior. Modern languages pride themselves on inferring programmer intent. TCL assumes nothing and requires you to state everything.

The ergonomic cost is real—more boilerplate, more opportunities for confusion. The benefit is precision. Reading TCL code, you know exactly which scope every variable reference targets. There's no hunting through outer scopes or consulting rules about closure capture. The code says what it means because the language requires it.

The Language That Persists

TCL peaked in the 1990s when its Tk GUI toolkit made cross-platform graphics programming tractable. Then Java, Python, and JavaScript offered better abstractions with larger communities. TCL usage collapsed but never disappeared.

It persists in test automation, where its string-centric design excels at generating and manipulating test cases. It persists in embedded systems, where its small interpreter footprint matters. It persists in Redis's design DNA, shaping how millions of developers think about data structure servers without knowing TCL exists.

Mostly it persists as an example of an alternate path not taken. What if we designed languages around text manipulation instead of type systems? What if we made scope explicit instead of inferred? What if we collapsed the distinction between code and data entirely?

These questions matter more than TCL's market share suggests. Every generation of developers rediscovers these design tensions. The answers TCL provides aren't fashionable, but they're considered. Four decades of production use have validated at least some of the choices.

Whether TCL remains installed on your Mac much longer doesn't really matter. The ideas it embodies—that strings can be a universal representation, that explicitness has value, that treating code as data enables powerful abstractions—those ideas keep surfacing in new contexts.

Redis isn't going anywhere. And Redis is TCL's most successful legacy: proof that deeply weird design choices, consistently applied, can produce something elegant enough to matter.

Bob Reynolds is Senior Technology Correspondent for Buzzrag.

From the BuzzRAG Team

We Watch Tech YouTube So You Don't Have To

Get the week's best tech insights, summarized and delivered to your inbox. No fluff, no spam.

Weekly digestNo spamUnsubscribe anytime

More Like This

Yellow crown and mustache logo with "nim" text on hexagonal dark background

Nim Wants to Be the Language That Makes Everyone Happy

The Nim programming language promises Python's simplicity with Rust's performance. Code to the Moon explores whether it delivers on that ambitious pitch.

Mike Sullivan·5 months ago·6 min read
Developer in orange hoodie working at triple-monitor setup displaying code and analytics with neon green and purple…

35 GitHub Projects Reshaping How Developers Work With AI

From AI agents that audit your setup to tools that make your Mac's hidden language model accessible, GitHub's latest trending projects reveal where developer tooling is headed.

Zara Chen·3 months ago·7 min read
A bearded man in a gray shirt holds a phone next to large "V4" text with Transformers.js logo and celebratory graphics on a…

AI Models Now Run in Your Browser. That Shouldn't Work.

Transformers.js v4 brings 20-billion parameter AI models to web browsers. The technical achievement is remarkable. The implications are just beginning.

Bob Reynolds·4 months ago·5 min read
Developer wearing orange hoodie monitoring colorful data visualizations on dual monitors displaying GitHub trending open…

35 Developer Tools From Hacker News That Actually Solve Real Problems

From AI agent memory management to thermal printer resurrection, Github Awesome's latest roundup shows what developers are actually building right now.

Tyler Nakamura·4 months ago·6 min read
Man holds military-grade measuring device outdoors with satellite dish and helicopter in background, yellow and red text…

Decentralized Tech: Gadgets for the Privacy-Conscious

Explore gadgets that blend tech and anarchism to maintain privacy and autonomy in a surveilled world.

Bob Reynolds·6 months ago·3 min read
Developer at triple-monitor setup analyzing GitHub trending projects with data visualizations and code on screens against…

34 Open Source Projects Developers Are Starring Right Now

From AI coding assistants to terminal tools, here's what developers are building in the trenches—and what it reveals about where the industry is headed.

Marcus Chen-Ramirez·5 months ago·6 min read
Bold orange and white "CLAUDE DESIGN" text overlays a dark interface screenshot showing grid analytics and UI design tools…

Anthropic's Claude Design: The Latest Bid to Automate Creativity

Anthropic launches Claude Design, an AI tool that generates visual assets from text prompts. But can conversation replace craft in design work?

Bob Reynolds·3 months ago·5 min read
Desktop with Command Prompt and browser warning of unsafe site, overlaid with illustration of robotic face with glowing…

What Happens When AI Gets Root Access to Your Computer

A YouTuber gave an AI agent root access to his Linux system. The results reveal both the promise and the friction of our autonomous software future.

Bob Reynolds·3 months ago·5 min read

RAG·vector embedding

2026-04-15
1,654 tokens1536-dimmodel text-embedding-3-small

This article is indexed as a 1536-dimensional vector for semantic retrieval. Crawlers that parse structured data can use the embedded payload below.