We can't find the internet
Attempting to reconnect
Something went wrong!
Attempting to reconnect
Analysis Summary
Worth Noting
Positive elements
- This video provides a clear, high-quality technical explanation of TCL's unique string-based architecture and its historical influence on modern tools like Redis.
Influence Dimensions
How are these scored?About this analysis
Knowing about these techniques makes them visible, not powerless. The ones that work best on you are the ones that match beliefs you already hold.
This analysis is a tool for your own thinking — what you do with it is up to you.
Related content covering similar topics.
Evolving Java is not about...
Java
Zig structs are cracked
Melkey
Clojure programmers: Cranky, tired, old? — Rich Hickey
Fred Overflow
Why Ruby?
David Heinemeier Hansson
Prime picks one language (Challenge Level: Impossible)
ThePrimeagen
Transcript
In my first ever role as a software developer, the main programming language that I used was C++, which given that the role was in finance, was kind of expected. What was unexpected, however, was the second language that we used, which was a language that at the time I had neither heard of nor encountered. In fact, I'm betting that most of the people watching this video either haven't heard of this language or haven't written any code in it before, despite the fact that it's installed on Mac OS by default and in some Linux distributions as well. That language is tickle or TCL, which stands for tool command language. And to this date, it's perhaps the weirdest programming language that I've ever learned. one that I not only often think about to this day, uh, but it's also inspired one of my favorite pieces of software, Reddis and its forks, such as Valky. But what exactly makes it so weird? Well, whilst there are a couple of properties that are kind of strange, there's one that sets it apart from any other programming language that I've ever used. This is because in Tickle, everything is a string. When I say everything in Tickle is a string, I mean quite literally everything. 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. All of which makes it without a doubt the weirdest language I ever learned. Speaking of which, if you yourself are interested in learning programming languages for back-end web development, such as either Python, TypeScript, or Go, and you also happen to be a fan of playing video games, then there's a good chance you're going to be interested in the sponsor of today's video, Boot.dev. Boot.dev is an online platform that will teach you the skills to become a back-end web developer using either Python, TypeScript, or Go. Rather than just teaching you how to code through lessons and tutorials, boot.dev instead aims to do so interactively by getting you to actually write code and build projects. In addition to this, the platform also aims to make learning as enjoyable as possible by taking inspiration from role- playinging video games. This means whilst you're learning to code, you'll also be gaining XP, leveling up, and earning achievements. If all of that sounds too good to be true, well, you can actually test it out right now, as each course has a free demo of the interactive experience for you to try uh before you buy. If you do decide you want to purchase and unlock all of the interactive features that the platform provides, such as code challenges, AI assistance with Boots the Magical Wizard Bear, and the recently released training grounds, where you can attempt personalized code challenges that have automatically been generated for you, then you can get 25% off your first purchase by using my coupon code, dreams a code when checking out. That's 25% off your first month on a monthly subscription or your first year on an annual one, which is a really good deal. So to try everything that boot.dev has to offer, then visit using the link in the description or QR code on screen and use my coupon code dreams of code to get that 25% off your first purchase. A big thank you to boot.dev for sponsoring this video. Okay, so before we dive into everything being a string inle, uh let's take a bit of time to actually understand how strings work by writing a good old-fashioned hello world. In order to do so, we're going to first need the TCL runtime installed on our machine. If you're using Mac OS, then this is actually installed by default, as I mentioned earlier. However, if I go ahead and launch this version, you'll see that I get a warning letting me know that one day it may not be available. And if I go ahead and print out the version string, uh you'll see it's a little bit behind the most recent one at the time of recording. So, I recommend instead installing the most recent version uh using something like Homebrew, which can be done using the following command. Once the installation is finished, we now have access to the TCLS sh command, which we can use to either execute TCL scripts or also use it as a ripple. For the moment, let's take a look at how to do hello world first using the ripple. To do so, all we need to do is use the puts keyword with the string that we want to print out. In this case, hello world. As you can see, pretty simple. Whilst the ripple is useful for experimenting, it's not as easy to write more complex code with. So let's instead take a look at how we can actually write some code in a file. To do so, we'll first create a new file called hello with the extension of TCL. In my case, I'm doing this in Neovim. Once created, let's go ahead and now write a script to say hello to a name. Uh rather than just saying hello world. To do so, we can create a new variable using the set command, which takes two arguments. The first of which being the variable's name uh which in this case is called name and the second of which is the value which I'm going to set as dreams. By the way, if this syntax reminds you of either Reddus or Valky, then you'll be interested to know that this is not a coincidence as the creator of Reddus Antierz took a lot of inspiration from Tickle and actually implemented his own TCL interpreter. In fact, the first ever version of Reddus was called LMDB and was in fact written using Tickle. see if you can spot any other commands that are also found in Reddus/valky. And if you do, drop them in the comments down below. In any case, with our name variable now defined, let's take a look at how we can print it out in our hello string. To do so, we can again use the puts command, passing in a string like we did before. Then, in order to reference our variable, we can do so using the following syntax of dollar name, which is similar to languages such as PHP and Pearl. TCL will automatically substitute this variable into our string when we define one using the quotation marks as we've done. There is another way to define a string without this behavior which we'll talk more about in a second. Now if I go ahead and run this using TCLSH passing in the file name you can see it prints out hello dreams to the console. Pretty simple. Okay, with that we've managed to look at how to do hello world and also how to quickly set up a variable and pass it in using string interpolation. However, one thing to note before we move on is that there's actually two different ways to do strings when it comes to TCL. Let's say, for example, we want to actually print out dollar name rather than it interpolating into our value. To do this in tickle, we need to define our string using braces rather than quotes. Now, if I go ahead and run this code, you'll see it prints out dollar name rather than substituting it with the value of dreams. As I mentioned, both braces and quotations are used to create strings in TCL with the key difference being that braces won't substitute values and quotation marks will. This is a really important distinction to know because, as I mentioned before, everything in Tickle is a string. This includes things like you would normally expect, such as types, of which there are only strings, but it also includes things in the language itself. To show what I mean, let's go ahead and create a new file and add in the following line. Here I'm setting a variable called code with the following string of puts hello from a string. Now, if I go ahead and print this line out, you can see it's just a string. However, because everything in tickle is a string, then this is also valid code that can be executed. Uh, which we can do using the eval command. As you can see, this causes the code string to be evaluated and executed. And we're now printing out hello from a string. Very cool. However, as I mentioned, everything is a string. I really cannot stress that enough. This also includes commands such as the eval command itself. This means we can go ahead and store the command that we want to execute eval as a string. And then we can use both our command and code variables in the following way, which if I go ahead and execute, uh, you can see acts as if it's just normal code. As you can probably guess, this makes the language incredibly dynamic, as well as making it work in some rather weird ways. This is especially true when it comes to things such as numbers and expressions, of which Tickle basically looked at how JavaScript does it and said, "Hold my beer." To show how expressions work in TCL, here I have a simple string that is attempting to add two numbers together. In order to execute this expression, rather than using the eval command like we were before, we instead use the expr command which is used to resolve both mathematical and boolean expressions. Here I'm wrapping this command inside of a pair of square brackets which basically tells the language to resolve this command first and return the result. Uh similar to using parenthesis in other languages such as lisp. If I go ahead and now run this code, you can see it prints out the result of the spring expression that has now been resolved. In addition to types, expressions, and commands being strings, perhaps something even weirder is that functions are strings as well. To define a function in TCL, you use the proc command uh which is shorthand for procedure. Then you define a string representing the list of arguments and a string containing your functions body. This function body will then be evaluated whenever the procedures command is called. Now, in order to call this function, I can just reference the functions name as follows, passing in the argument of world. One thing you'll notice is that I again used braces to define these strings instead of using quotations. And there's a couple of reasons as to why. The first is that this is more idiomatic and also makes the code a lot more readable, at least in my opinion. In fact, by using the braces this way, it makes the language look very similar to the syntax of C. The second reason is more to do with timing around substituting variables versus when a string is evaluated. In order to better showcase this, let's take a look at the next reason as to why tickle is kind of weird, which is the fact that the language has no statements. In most programming languages, you typically have what's referred to as statements with perhaps the most common one being the if statement uh which you use to perform branching logic. TCL or tickle again is slightly different. And whilst it does have if, it's not actually a statement. Instead, it's a command, but one that does work in a rather similar way. To show how the if command works, let's go ahead and write a quick example where we want to check if the value of a number is greater than zero. And if so, we're going to go ahead and print out to the console. To do so, let's first begin with the if command itself, which accepts two arguments. The first of which being a string that contains a boolean expression. In this case, we're checking to see if the number is greater than zero. As an aside, tickle represents boolean values as either a zero or nonzero string, which you can see in the results of the ripple on the right hand of the screen. With our expression defined, the second argument that the if command requires is a string that will be evaluated if the boolean expression resolves to true. In this case, I'm passing in a string which contains puts hello. Now, if I go ahead and run this code, you can see that hello is printed to the console because our expression resolves to true. To prove that this is the case, if I quickly change num to be zero before rerunning it again, this time hello is no longer printed. Once again, you'll notice that I'm using braces to define both the expression and evaluation strings. This is again the idiomatic approach, although in this specific case, it would be fine to use quotations for either one. However, the same can't be said for the next command we're going to look at, the while command, which is used to create a while loop in Tickle, uh, similar to other languages. To show how this works, let's go ahead and quickly create one that performs a while until the value of num is greater than five. To do so, I'm going to go ahead and use the while command passing in my boolean expression for checking the number as the first argument followed by the loop body, which in this case is using the incre command to increment the value of num by one and then print it out using the puts command. Now, if I go ahead and run this code, you can see that it works as expected. However, as I mentioned, the brace defined string is really important when it comes to the while command as it allows the string to be evaluated in each loop iteration rather than the value of num being substituted once when the string is encountered. To show what I mean, if I go ahead and change the boolean expression string as follows before then running the code, you can see we get stuck in an infinite loop. This is because the value of num has been substituted with the value it was when the command was invoked uh which was zero. The same is true if I change the loop body string to use quotations as well. As you can see, we get stuck on the value of one because the value of zero has been substituted in the original string. By using braces, we stop the parser from substituting num too early. Instead, the while command evaluates the expression each time through the loop. So, the condition stays dynamic instead of being frozen at its initial value. In addition to the while loop, other looping commands that are available in TCL include the for command, which is used to effectively create a for loop, and the for each command, which is used to explicitly iterate over a list of elements. Speaking of which, this segus nicely into the next weird feature of TCL, which is how it handles non-scaler data types such as dictionaries and lists. In TCL, lists are again just strings, ones that are structured where each element is split by the space character. This means we can define a list as follows, either by using quotations or braces. Of course, lists by themselves aren't exactly that useful. However, TCL does provide a number of commands that you can actually use with structured lists in order to access properties such as llength which is used to return the number of elements in a list. L index which is used to access an element within the list. L append to append an element to the end of the list. L insert which is used to insert an element within a list. And L range which is used to perform list slicing. As I mentioned before, you can also iterate over each element inside of a list using the for each command as follows, which accepts three different arguments. The iterator value, the list you wish to iterate, and then a string that will be evaluated with each item. As you can see, all of this is still just using strings, which I can go ahead and prove by printing out the value of my list, which you can see is just a list of elements separated by the space character. Of course, this brings up a good question. How can we create an element inside of a list that contains a white space inside? Well, when it comes to CCL, there's actually two different ways to do so. The first approach is to use braces to define the list and then use quotations to define the element that contains any white spaces. This is the preferred approach if you're statically defining a list. However, if you want to preserve elements with spaces inside when creating a list with dynamic values, then you need to instead use the list command, which is done similar to the example on screen. In either of these approaches, because again, a list is just a structured string with white space between each elements, then we've actually managed to create a sublist inside of our string, which means we can pull out elements as if it was a 2D array uh using something like the following lindex command. As you can see, lists in Tickle are kind of weird. But they're not the only data structure that follows this structured string pattern, as this also applies to dictionaries as well. In Tickle, a dictionary is a key value data structure, similar to maps or dictionaries in other languages. However, as I mentioned, in Tickle, they're represented as a structured string similar to lists with each key value pair separated by a whites space character. To show what I mean, here I have a dictionary called Saiyan, which is represented by the following string. This dictionary contains two key value pairs. The first called name with the value of Goku and the second called power level with the value of just over 9,000. Similar to lists, dictionaries also have a number of commands you can use to access and modify values within them, although these are accessed through the dictic prefix. So let's say we want to access a value inside of a dict, we can use the dict get command. And if we want to set a value, we use dict set. If I go ahead and print out the value after this dict set, you can see it's modified the original string. One thing to note with dict set is that this takes the name of the variable rather than a reference. Otherwise, it won't actually update the variable's value. This is similar to other commands in TCL, such as the incro command, which is one we've seen already, but is used to increment a value by a certain amount. Next, we have the unset command, which is used to delete or unset a value, and the info exists command, which is used to check for the existence of a variable and resolves to a boolean expression. For a full list of the commands that TCL provides, I recommend checking out the documentation of which there's a link to in the description down below. Okay, so this next feature of Tickle is one that's not actually related to everything being a string and instead is to do with how Tickle manages scope. In most other programming languages, scope is implied. For example, if you define a variable inside of a function, then that variable is locally scoped to that function without you needing to define it as such. The same goes for global variables as well. When it comes to tickle, however, scope is instead explicit, meaning there are times you need to explicitly define the scope of a variable in order to access it. To show what I mean, here I have the following script. On the first line, I'm defining a variable called x with the value of 10. Underneath it, I'm then defining a procedure or a function called print that accepts zero arguments and prints out the value of x. If I try to run this code, you'll see it produces an error letting me know that the X variable isn't available even though I've declared it globally. So, how can I actually make this work? Well, in order for a procedure to have access to a global variable, we need to explicitly mark it as a global variable inside of the procedures scope, which I can do using the following global command. Now, if I go ahead and run this code, you can see that it works as intended. In addition to global scope, TCL is also explicit when it comes to passing in values by reference. In this case, if I want a function or procedure to modify a value that's been passed in, I would need to use the upvar command to bind the variable to one that's inside of the local scope. Now, you can see I've created a variable called v, which I'm then able to modify. And this will then also modify the value of the variable that was passed in. Basically, we've explicitly defined the scope of X to be passed in by reference. If that wasn't weird enough, then this next command makes scoping in TCL. Even weirder, this is the uplevel command, which allows a procedure to climb the call stack and execute code inside of a different scope. For example, here I have a function called outer which sets the value of x to 42 and then calls the inner procedure which as you can see does uplevel one which means it ups the call stack by one and then prints out the value it from inside of outer. If I go ahead and run this code you can see that the inner procedure is able to access the x value defined in the outer procedure and prints it out. Now I know what you're thinking. Why the heck would this command ever exist? Well, that's a good question. and fortunately one that does have a good answer. The reason this exists is because it enables the ability to create DSLs, perform meta programming, and perhaps more importantly create your own control flow commands. To show what I mean here, I've defined a function called range, which is used for iterating over a range of values. This function makes use of both the upvar and uplevel commands to provide a similar interface to the built-in for command. The upvar command is used to update the loop iterator variable and the uplevel command is used with the body value in order to move the scope of execution up one level to where the loop is called. As you can probably tell, tickle is an incredibly strange language. But because of these quirks, it actually makes it rather useful in a couple of key areas. The first of which is when it comes to tickle's main use case, which is for embedding into other applications. Whilst Tickle can be used as a language by itself, it's more than capable of doing so, it mostly shines as a scripting language that you embed into other systems. This is because both the language and the data are one and the same, allowing you to easily perform dynamic scripting in ways that can be challenging when it comes to other programming languages. This is in fact very similar to the role that Lure plays when it comes to neoim or in-game engines and also the role that ELIS plays when it comes to configuring Emacs. As for how to embed TCL, well, this is actually rather simple. By default, there are bindings for both C and C++ which allow you to then bind functions so that you can call them from within the tech context. This can also be used with languages that support FFI or foreign function interfaces such as Zigg and Rust. Additionally, when it comes to Rust, there's also the molt crate, which stands for more or less TCL. Molt is a native Rust implementation of the Tickle interpreter, one that's almost feature complete, although there are a couple of things missing. So if you need full language specification support, uh then it's best to just use FFI. In addition to C, C++, and Rust, however, perhaps the most common integration of TCL in a programming language is when it comes to Python, specifically related to the TK inter package. This package is used to create application user interfaces in Python. And under the hood, it makes use of tickle. On first glance, this may seem somewhat strange, but it in fact makes a lot of sense. This is because tickle is generally paired with another package called TK, which happens to be a guey framework and is the second main reason to use the language. Typically, when most people refer to Tickle, they actually mean Tickle/TK. In fact, when we installed the package through Homebrew, uh you'll notice that we installed it with tickle-ts and for the longest time was the easiest way to build crossplatform guey applications. And I don't just mean easy for the time. I mean genuinely simple, even by today's standards. To show what I mean, here I've created a really simple guey application using TK which has three different elements. a label which displays a count, a button to increment the count by plus one, and then a button to reset the count back to zero. By the way, if you want to play with this code yourself, there's a link to a gist that contains it in the description down below. And to run it, you just use the wish command as follows. Whilst this is a really simple example, you can see from the code on screen that it was very trivial to build and only took 26 lines of code in total. This is the main benefit of using TK as it makes it incredibly trivial to build simple native looking UIs for existing applications without needing to use a fullfeatured UI framework. This gives tickle an edge when compared to languages such as Lure or Lisp. Although typically JavaScript is more commonly used in the modern era of software development when it comes to creating UIs. Despite this, TK is still a really interesting framework when it comes to building user interfaces and one that I would recommend playing with if you're interested. In any case, as you can see, all of this makes TCL a rather fascinating, if not slightly strange language. And whilst it may be a little quirky, especially from a more modern context, it's still a language I'm really glad I got to learn. Speaking of learning languages, I want to give a big thank you to boot.dev for sponsoring this video. If you're interested in learning back in web development using either Python, TypeScript or Go, then go check them out using the link in the description down below or the QR code on screen. And if you do decide to get a full membership, then make sure to use my coupon code dreams a code to get that 25% off your first purchase. Otherwise, that's all from me. But I want to give a big thank you to you for watching and I'll see you on the next one.
Video description
Click this link https://boot.dev/?promo=DREAMSOFCODE and use my code DREAMSOFCODE to get 25% off your first payment for boot.dev The first ever programming language I learnt was C++, which is probably one of my favorite languages to this date. This also happened to be the first language I used professionally, in my first ever software developer role. The second language that I used professionally however, is one that I had never heard of before... one that ended up being quite strange. Watch my course on building cli applications in Go: https://dreamsofcode.io/courses/cli-apps-go/learn 👈 Links: TCL Docs: https://www.tcl-lang.org/man/tcl9.0/ GUI Gist: https://gist.github.com/elliottminns/1e0a11c9b629db8339de7512878bea97 My Video Editor built in Rust: https://getkiru.app My Gear: - Camera: https://amzn.to/3E3ORuX - Microphone: https://amzn.to/40wHBPP - Audio Interface: https://amzn.to/4jwbd8o - Headphones: https://amzn.to/4gasmla - Keyboard: ZSA Voyager Join this channel to get access to perks: https://www.youtube.com/channel/UCWQaM7SpSECp9FELz-cHzuQ/join Join Discord: https://discord.com/invite/eMjRTvscyt Join Twitter: https://twitter.com/dreamsofcode_io 00:00:00 Intro 00:01:45 Sponsor 00:03:13 Hello World 00:06:01 Strings 00:07:46 Expressions 00:09:43 Statements 00:13:02 Non Scalar Data Types 00:17:01 Explicit Scoping 00:20:03 Embedding 00:21:37 TK