 All right, there we go Okay, so I want to welcome everyone It looks like we've got a number of new attenders. So this is the Houston functional programming users group and Yeah, it's nice to see everyone here This is the first meeting we've had since we sort of went back to meet So that was something that a few people were asking mostly for the automated reminders So I'm curious is if the meetup actually had Did people learn about this through the meetup or how did people learn about this meeting? Sorry, I saw a message on hacker news. So I cry I am crashing this meeting On hacker news that that's pretty good because I didn't post anything to hacker news. So that's nice I think it was an hacker news Yeah, I posted to Reddit Yeah I think I got it from a comp or CLP comp lag DCL Yeah, that thread got hijacked by trolls, which was really unfortunate Okay So just a couple of people I'm seeing that there's some stuff in chat Okay Let's see what else I want to mention. So yeah We're back it up for now to see how that works In November, we're going to have Jeff Olson speak on Functional programming with rust. This is something that David organized So I'm really excited because I know that there's a lot of interest in rust So that should be a nice Talk and then December is we traditionally have a Social meeting instead of like having a speaker or anything like that. I actually am not going to be in town the third Wednesday of December but I'm happy to organize and so what I'm wondering about is last year, of course We did it online because of COVID And we can set that up again if people want that or we could move to we could do a face-to-face Somewhere outside that had he has heat or is in case it's cold And so if you have a preference for those of you who are local in Houston and and want to do the social media Just shoot me an email or you can send something in the in the chat or whatever Let me know if you have any thoughts or preferences or anything like that I think that's basically all that I have to say business wise Any questions or thoughts or anything anyone want to jump in before I introduce Carl All right, so tonight's speaker is Carl lay in Bauer. Is that how you pronounce sure? That's your last name Okay Sorry Lee and Bauer, I mean the German is really weird but Lee and Bauer what's anglisized. Okay. Um, so Carl Lee and Bauer I'm glad to learn how to actually say your name. I appreciate that He is a long long time Tickle developer and contributor. He is a former member of the Tickle core team and and I should say at this point I know he's been pushing to have people pronounce it Tcl and so he might talk about that. I'm not sure but I'm still kind of stuck on the tickle So I go back and forth right now. So Yeah, the transition is difficult for me Okay, I Wanted to provide a little bit of an introduction Before I actually wrote it up, which is good for me a little bit of an introduction before turning things over to Carl Given that it might seem quite odd to be discussing tickle a functional programming users group One of the reasons for this is that Carl is local and I really did Want this talk to be in person that it was one of the reasons for sort of pushing it off and pushing off because he agreed to do this a long time ago Because as you'll see very soon Carl's a really good speaker and and totally fun It's smart and insightful So I was hoping we would do this in person, but COVID so Let's see So Carl Co-founded flight aware and this is the other sort of part about why he's here today He co-flight aware, which is a a the flight tracking company And it's based here in Houston and it is a tickle shop It's not the only language that they use and I think Carl's going to talk a little bit more about this But they are one of the if not The major industrial and I think that's interesting in and of itself one thing that people have always been interested in in this group is like sort of you know applied uses of Programming languages and then the other reason that I wanted Carl to present is that I think I think tickle is just really an interesting language and In this group, I know that you know, we're always really interested in Learning about different languages and their philosophies and their structures and all that As some of you know, I started using tickle a few years ago and it's really become my go-to language for scripting at this point Over the years at at the group. I've presented a couple of Present a couple of times about how I came to functional programming and specifically OCaml after sort of increasingly running into limitations and problems with using Python for the software that I write But OCaml wasn't all that great for front-end stuff and specifically for graphical front-ends, which which I'm also developing And so I was a few years ago Looking around is sort of looking at the usual suspects and trying to figure out what language to use and one of the things I kept running into was that sort of all of sort of the classic scripting languages now are the you know, the most popular ones Eventually they all said oh, but cross-platform distribution is problem and that was one of the things that I I had a problem with it as well and Here and there and then over and over I started looking into it everyone was saying like oh, but tickle Solved this problem decades ago like literally decades ago back in the last century tickle had solved the cross-platform distribution problem and So I started looking at tickle more seriously and I found this sort of funky little language that that to me at least was weirdly appealing It's more imperative than I would like now that I do functional programming and They have like lots of commands that might act differently depending upon which parameters You'll apply and and I generally dislike that and find that very sort of confusing although I'm getting used to it with tickle and Tickle That kind of thing of like the command might act differently depending upon the parameters that you supply tickle leans very very hard into being a dynamically typed language and one of the things to sort of try to appreciate here is that It's often better to think of tickle as untight not not dynamically type but untight because it really is the command itself that determines how its arguments are going to be interpreted The tickle language itself doesn't actually have a sense of typing per se and it doesn't enforce any of these constraints What's sort of unique about tickle here is that it has almost no syntax and This is one of the places where I see a lot of parallels with list The language itself is actually defined by just 12 rules Referred to as the dodeca log And the number of rules has sort of increased a little bit used to be 10 then to 11 now it's at 12 people seem to be pretty happy with that but It's really sort of important to understand this that that the first rule is that a tickle script is really just a list of one or more words Where the first word is a command and the remaining words are its arguments This is very list-like again and the other rules really just describe how the tickle interpreter is going to parse the list and perform substitution and argument expansion and That's really all that the tickle language itself is It's a set of rules for interpreting and executing these lists There aren't any reserved words, which I think is very surprising for a lot of people So even something like if is just a command And it's a command like any other in the language It's it just if takes a Boolean condition and either executes the first branch or the second branch and that's it And what this means is you can actually redefine something like this, right? There are no reserved words Redefining if is probably a bad idea Because it's used everywhere, but I've actually run into places where actually never did it But I've thought about it seriously because as some of you know, I my own work I work with this for-valued logic instead of Boolean just to valued logic and With okay, we'll in strong typing and all that Okay, well will warn me when I screw up and I Sort of think about something in in two values, but I actually have these four conditions. I need to test Tickle being dynamically typed untyped it doesn't do that But the idea of redefining if to catch those is actually really really Appealing and useful So these are some of the things tickles very very flexible My own sort of thinking when I was thinking about this today and writing up these notes. I Really wish I discovered tickle like years ago I Spent a lot of time like years and years sort of fighting with Python and against its limitations and in particular it's sort of constant churn in Libraries in its standards in its tooling and that was super annoying and and I've presented on that a Few times. So some of the issues I've run into Tickle is a lot simpler like it's kind of ridiculously simple in a lot of ways but one of the things that means is That it offers this like really incredibly flexible foundation that also allows it to continue to evolve and Because the language is so simple it also is very easy for it to maintain backwards compatibility So there are tickle scripts out there in the wild. There are libraries They're decades old at this point and they still just work and and that is absolutely wonderful The flexibility can also be a little overwhelming I was looking it up today and the ticklers wiki lists six different popular Object-oriented frameworks that you can choose from Which which seems like a lot except those are just the most popular ones. There's actually almost 40 out there Sixer of which are the are the popular ones. That's really good. People can pick what sort of works for them But it does also give you this additional need to sort of go through them and figure out What is it that's going to work for you? And for this group There are more and more functional features being added to the language. There are more libraries that are implementing functional practices and There's there's even pattern matching now in in a library. I haven't actually used it But there is pattern matching my favorite command that exists is there is a tail call command that You can use when you're doing your recursive functions and you put in tail call. It's very explicit But there it is and it replaces, you know the command on the stack So it's it's it's very very nice. Okay, um Flight aware turning I'm going to turn things over to Carl a second. He's the CTO of flight aware Which also sponsors the annual SQLite and Tipple conference. It's held here in Houston every year Carl organizes it and This is where I first met Carl actually when I went to the Tipple conference for the first time This year like last year the conference is going to be held online and it is free so you can sign up and Attend virtually it's going to be on wednesday november 17th It's going to be from 10 to 3 p.m. Houston time And so it would be nice if if you want to join us I'll I'll definitely going to be there and we're going to learn all about sort of lace developments surrounding SQLite and tickle If you're not aware SQLite originated as a tickle extension And the connections between the SQLite and Tipple communities Continue to be very very deep and so it makes a lot of sense to put these two together So I'm going to stop talking now. I'm going to turn things off Turn things over to Carl. So thank you so much, Carl. Thank you. Thank you quad Hi everyone So I'm going to start this introduction to okay, so tickle tcl right The name definitely was tickle I think it's unfortunate. Uh, one of our marketing people was like a bunch of grown men talking about tickle is weird So, um, I wish we called it something clever like java. I think the language would have been a lot more popular Obviously not java, but you know what? I mean a cool name a better name. I don't think the Inventor was particularly good at naming the language But I'm going to I'm going to try to call it tcl I'm going to I'm going to start this introduction. I'm going to show you some simple list Functions and approximate tcl equivalence just to give you a feel of how much it how much it is kind of list like Um, then I'll teach you some tcl by showing you more code And I'll talk about the evolution in my thinking about software development kind of go through some aspects of my My career and my experiences what I've done about it Back to more tcl and then I'll talk about flight aware and how we do what we do and where we think we're going So I studied computer science at indiana university in the late 1970s And it was a real computer science program not some double e program with a couple of software electives Which was exactly what I wanted because I was in love with the malleability of software And I wanted to leave the creation of the machines themselves You know, which was a much slower process to others So one of the 300 level computer science classes was on programming languages and we learned in their lisp algal and snowball So I thought lisp was super cool. I liked its facility with lists big surprise, right? Although we learned the three languages we spent almost the entire semester on lisp And we of course wrote a lot of recursive functions and learned about backtracking and rhodate queens and Generally had a jolly good time So let's go to the code. I'm going to be demoing using jupiter notebook I've got one on the left running a common lisp kernel and the one on the right running a tcl kernel Just give me a sec here Line the share button. There we go All right. I think you can all see that right? Is it is that reasonable? All right, so On the left here, we'll go into the first cell and hit run and and we see that lisp if we Give it a number or an atom or something like that. It'll just return that We'll try that on the tcl side and we get an error Okay, because because it's trying to invoke one as a command a little bit of a difference there But if we say, oh, I want an expression of one We run the expert command and give it one as an argument and it returns one On over here on the list side. We'll set. Uh, we'll set c to 42 And on the tcl side Set c to 42, right Uh, we'll define a a silly little function that adds two numbers together But but this is cool because it actually illustrates a couple things Uh, so we define plus there and we run it and we get the expected answer and We'll come over here and we've defined plus and you can kind of look at those things A little bit side by side there. Let's see And uh, you know, they're they're close, right? One thing you'll notice is it's not wrapped, you know with brackets or parentheses like the Function is in lisp. So I'll define this And run it and I get the same result Um, then one of the things I want to point out here is there's not an explicit Like list the last thing that you do is the source of the return Um in tcl, that's true too. I could have gone here and said a return of expert of a plus v and that would have worked too And if we do that that works, but um, but it's it's similar to lisp in the sense that there's like a result, um, a result inside the interpreter that that is returned by default um Here on the list side Let me just make that a little narrower um We'll set a to an s expression now my my lisp. I I Knocked a little rust off by lisp this week getting ready for this thing, but uh, if I if I'm revealing 1980 Undergraduate list skills and oh my god. I can't believe you're using that dopey way of doing things. Well, you know, sorry about that So here we got the s expression right a b and c in a sub list and uh over here On the tcl side. We have the same thing. Um, again, it's not wrapped with the list, but that's a legal list I think it's important to reckon it's kind of interesting everything in tcl is a string So a list is a string that has um the correct formatting to be a list now Later versions of tcl meaning once in the last like 20 years have um Well, yeah, something like nearly 20 years Behind your back it does all sorts of caching and object creation and you know if if it sort of recognizes that that string Has been used as an integer it will cache the fact that it's an integer and it won't constantly convert it willy-nilly back and forth between text um On the list side then the familiar car there and cuter Do their familiar thing and on the tcl side l index Of zero is an equivalent to car Contents of the address register. I don't know if y'all know that Contents of the decrement register what those things stand for List brand on an ibm 709 I had the chance to actually meet john mccarthy It he came and did a symposium at the university while I was there. That was pretty cool Yeah, so okay, so and then here on the list side nth will will let us get a particular element of the list and on The tcl side l index so we'll do the same thing and produce the same The same result so here for fun. We define car and cuter as You know L index of zero the first element of the list and then l range of list from one to end End is a magic keyword. You can do arithmetic across it and stuff and then we run car and cuter and we get the same results as we got On the list side Um Commands are A list of arguments. It's a is as quad mentioned in his introduction there. See we've got this It's just prok Is the command and it takes three arguments the name of the prok the arguments in the body And so even that it's a multi-line body. You see this does have the list of structure one two three Four four values. So it's kind of cool Over here we'll set a variable And we'll increment it On the tcl side we'll set a variable And we'll increment it and we'll increment it both ways. So anchor is a shortcut The that can increment and it can take an optional argument of a amount to increment by which can be negative Or we can do it now I think I should speak for a minute right here about the I tried to get you know, it was hard to get people either really like lisper. They don't I think you know and Trying to get regular people to learn lisp and they didn't like all those parentheses, right? And I thought that I thought that tcl could get you to a lot of lisp stuff And maybe be a little easier to wrap your heads around and I mean for What I would call like a journeyman developer like a competent developer but not a rock star who's willing to sit there and like really drill into something and figure it out And and tcl has been pretty popular It's like about the 50th most popular language still on that language popularity thing, which is not bad but This thing where you have to actually invoke expert to Evaluate an expression. It's it's way simpler, right because now the parser doesn't know anything about this thing That's just an argument an expert figures it out but That bummed a lot of people out and I think that kind of hurt the language although it's weird It would be weird if it worked any other way And and again that feels to me very very lisp like um So here we've got the classic, uh, let's see we'll run the uh, we'll run x here and get our three and A's Give us the list still. So here's a classic definition of factorial on the left near the bottom from lisp, right? recursive factorial function and we'll run that And we'll do factorial 40 and we get a really big number which shows that lisp is supporting really big numbers way bigger than a I think that's way bigger than a long long. That's uh, that's some kind of magic big big big number Uh, so over here on the tcl side. We see This is a very similar factorial function. I'll put it next to that you can see it's Basically the same thing Relying on the the return thing and we run it and You know, I didn't check otherwise that these numbers Are correct, but it did produce the same results. I'm going to guess that really is 40 factorial Here's a little fancier Version that gets it into one statement And I and I like this one because it also shows There's kind of a c syntax if you know c to expression. So the you know, it's You can say in c Something you know a comparison and then if it's true it does the one value or if it's false it does the other and so This factorial function also Works and does the magic thing Um Yeah, cool. Okay, so uh, I'm going to show you a little more about lists lists here Uh, we're going to make a list with the list command and then we're going to iterate through it with four each And we'll print out some stuff So there's the value of each of the list elements in the square Of the element and we can ask for the length And of course, you know, we can we can You know set one to a length of dollar l You know And uh, you know put dollar one or something, you know, so we always can just wrap anything in square brackets and get it I'll put and do something with that There we're gonna we're gonna append it to the list another value And that worked There are several list commands, you know, one thing, uh, I bought a Common list book a long time ago and I was kind of blown away by just how thick it is with all the commands And it's a little hard to wrap your head around one thing that's kind of nice in tcl is There are a lot of commands that kind of have sub commands. So instead of a million string commands The string command has a lot of little sub commands. So you could say like string is integer string is float string is You know, uh, printable or whatever all all sorts of you know string first string last string range All sorts of string operators are within this command called string, which is kind of nice So here i'll invoke el insert with no arguments and I get an error Saying that uh, you know, I think with the right arguments and I've got to give it a list and an index and then possibly some elements Here we'll do it right and Uh So we inserted hello in the middle of the list now it didn't actually put that into the list. So if we Emit the list again, it doesn't have the hello A little more Playing around with lists. So here l is set to the string which happens to have a list format Um Actually here we're setting l again and it still has a list format the difference Is that if inside the double quotes if there's any dollar signs or score brackets It will do the substitutions and and inside the curly brackets and won't It's kind of cool So here's sort of a classic. This is a little simplified password file line from unix Um, and so we've set that into a variable and then Those of you probably all know that uh, it's a colon separated set of columns and so here we can Split on colon and get a list of that thing now made into a pure tcl list and here we can Grab particular Elements out of the list by indexing into the list That's sort of a pain Um, so we have this l assign command that will let you Assign successive elements of the list to to various variables and You can see that that works. Um, that's really handy. That's something I stole from pearl I don't think very much of pearl, but I kind of like that it could do that I think that's turned out to be really handy And eventually it became part of the tcl language Here we're going to take the list and join it back the reverse and split And so there's that same line only now with vertical bars instead of colons, you know turning that into a string And of course the original, you know back in that um So there are a lot of different list commands here's a l sort, you know, which will sort a list It has l sort has switches you can sort of sending and descending and you can sort integers and and all sorts of very cool things You can span Things so you can have some kind of complex data structure and still sort Possibly sort depending on how you set it up L search will search a list and then give you the index in the list of the thing you're looking for and it has switches for patterns and and all sorts of Glob and things like that All good interpretive languages should have the ability to evaluate a string that contains Code in the language. So tcl is no exception. It has a val And here will a val of set of a variable. That's kind of goofy, right because I could have just set the variable anyway but Uh I want to say about that. Yeah, no, I mean, you know, you can build up complicated tcl code and eval you can write You can write code that writes proxies. So it's really easy to do metaprogramming Here's glob. This is like File name expansion, right? So if I glob that here's all the files that are in the directory that i'm running cheaper notebook from I can l sort the output of glob and now they're in order Um here just to kind of bring it all together. We're going to iterate file over the l sort and list the files Kind of gives you a sense, right? um Here we're just going to introduce that tcl has the option you can create uh default values. This is kind of dopey a plus that runs with If you only give it one argument it assumes zero is the other value, right? Uh, now, well, what if I want to make a plus that can do More than two values. Okay. Well, I'll just call plus with three values. It's like no, it's gotta be One or two values. Okay, cool Well, you know, oh, I can look at the error info and see what's going on with tcl and there's also an error code that's Machine readable So you can catch an error and you can uh read into this like uh, for example, I'll make another one here if I Try to um, you know open slash temp slash garble, you know, it's not gonna work Run it quit and open And I'll say a post dollar error code And you can see that we got a tcl list here So the first uh element is posix telling us it's a posix error Then it's the e code from posix eno and and then the Error string as a list element and that's in your uh native You know Native language so that that might be different in another language So, you know, your code can look for the posix and the eno and and know that the you know what that means um So here's a version of plus That takes a variable arguments. It has this magic tcl thing called args And then we run plus and and we solve it the hard way newton solved it As a young man Okay, now this is cool. I had mentioned eight queens and um while I was preparing this talk I um, I had remembered that I had tried to write eight queens back with tcl in early 1991 or so And uh, this is this is the code that did it. It actually worked without any funny business at all The what we're going to do is the the board is just the list of Positions of queens from one to eight and so it'll be a a solution will be a vector of eight values and um And this does backtracking, right so so what it does here is it starts And it uh, places a queen and it places a second queen It asks if they're legal and if they're not it moves the second queen and asks if they're legal And if they're not it moves the second queen and asks if they're legal and then they are right and so On eight queens when you're push it when you're putting the second queen and you reject a position, then that's 262,000 something positions that you're, because of backtracking, you know, if I have two queens in the first row, I know I don't need to look at other queens in the row versus some brute force thing. So if we run this, okay, invalid commanding echo, where did I leave echo in here? That's from, remember I just said everything worked. Yeah. Well, we'll put a package require TCLX in here. This shell used to have that built in, try it now. Okay, there it is. So there's all the solutions. I think there's 92 or 96, something like that. But let's go ahead and let's dump out what legal is doing, what legal's inputs are so you can see the backtracking. This is kind of fun. Okay, so like, oh, legal one, one, no, one, two, no, one, three. Okay, legal, one, three is legal. One, three, one, one, three, two, da, da, da, da, da. So it's building up the board, you know, and when it gives up on one, it doesn't look any deeper at that level of ply. So here pretty soon, it's gonna print out a solution as soon as it gets a whole set of things. So it's crazy. The program blows up pretty fast. Like if you do 12 Queens, it still takes it about a minute on my Mac. Now I wanna see it say Sol here somewhere. Anyway, you get it, right? It's kind of cool, there was one. There it is. Yeah, so that's a backtracking solution. It's pretty tiny actually. I was looking at some of the Lisp solutions and they're bigger, but it kind of cheats because it just prints out the boards instead of building up a list of all the boards and returning it. Let's look at some more TCL code just so I can sort of introduce you. This proc right here would stood in and stood out are special names that gets and puts recognize. So this would read every line from stood in and pass it to stood out. Copy file right here would take, oh, there's a bug. I've copied this by hand. You gotta open the output file for write and then that would copy and close the files. There's a try and on error, you know, and a finally. So that's come into TCL recently which is like in the last 15 years. And so you can put a finally on there and make sure that you do the close even if the thing blows up, you know, which is kind of cool. So this is sort of interesting. Here's another proc that opens a file and reads the lines and writes them up. But notice it's got the little pipeline symbols. So this is like, oh, I wanna open a pipeline from who? Let's define the proc and then run it. And then boom, here's the users on the system. I know that guy. And here's another way to do it. So TCL at the very beginning, and I'm gonna talk about this in a second, it didn't even have files. So you had to use exec. So this is how you might run who you run exec that runs the command and returns as a string, whatever the output of the command was. So if I do it that way, get the same result. It's kind of cool. All right, let me stop sharing for a minute. I'm gonna talk for a few minutes now about my career and some insights that I developed and ultimately put to use at FlightAware. So going back to that programming language class, even though we only spent a couple of weeks on it, I also thought snowball was pretty cool. Snowball has a legacy back to Bell Labs in the 1960s. And despite some quirks, it was really good at text. You didn't have to allocate strings to be a certain size. You didn't have to manage their lifetimes. That was all handled behind your back. It could do pattern matching. It could do substitution with something that was a Ken. I would say it's a forerunner to regular expressions. It had associative arrays that is arrays where the indexes could be arbitrary text. And I found that to be incredibly useful. So I found part-time work at the university and I developed something of a specialty helping grad students fix irregularities in the formatting of their data sets so that they could get them into SPSS, which was the statistical package for the social sciences and stuff like that. So the thing would be that they hadn't considered a family could have 11 kids and so the data format wasn't wide enough or whatever. So I would write a little program to straighten them out, kept me in beer money and stuff. And Snowball became my go-to language for this. I'd write these programs and they would be 50 lines of code and I would just marvel at them and go, my God, if I wrote this in Pascal, which was the kind of university language that everyone was using for everything at the time, it would be thousands of lines. I felt a little guilty that my Snowball program might take 200 CPU seconds on the CDC 6600 mainframe while Pascal would have taken 10. But these were all one-offs and I could really deeply see the value of making the computer work harder if it meant I could work less hard. So around that time, I got introduced to UNIX maybe 1979 and it was a revelation in so many ways. Without a doubt, it's had a profound impact on my career and how my life has gone. The complete simplification and abstraction of how files worked, the shell, pipelines, how you started processes, the C language as a systems programming language, the quality and the conciseness and the beauty of the documentation were just totally compelling. And it was really, really good at text. Also at text. So I began to use the UNIX tools to help get people's data squared away as well as getting people going and formatting their papers using TROF which was the main reason they bought the machine. The last thing I want to say about UNIX right for now just for now is that the operating system made heavy use of text files, the password file, right? Define the users, the group file, define the groups, the services file later, define all the TCP IP services that might be available. Like all these text files configured how things work even as the operating system booted up, the last thing it did was it ran a shell script and the shell script launched the programs that allowed you to log into the terminals and things like that. And that was really unprecedented and it was much more flexible than what preceded it where users could only use privilege tools that the operating system provided to perform binary edits of these rigid data structures that represented users and so on. And this is ubiquitous in UNIX today whether it's like formal UNIX, Linux, one of the versions of Berkeley or whatever they all work that way. Okay, so I get out of school and I get jobs doing real-time stuff and I get to a power company and I'm programming control systems that dispatchers interact with to monitor and control the power grid. And it was pretty heady stuff for like a 22 year old that my software is throwing giant circuit breakers and raising and lowering the output of generators. It sounds like a heavy scientific application, right? Like a lot of floating point and we have some but I had this epiphany one day when I realized that most of our code, what our code was doing, most of what the processor was doing in order to control the power grid was it was moving text around. The lion share of what the CPU cycles were going to was drawing stuff on displays, reading operator input, constructing messages, queuing them, showing them on displays, printing them, et cetera. So that was kind of a big deal and it was counterintuitive at first and it was all the code was written in FORTRAN which is a terrible systems programming language and terrible at text. And when you were doing text it exposed the word size of the machine. So if you were on a 16 bit machine you explicitly knew they could store two bytes in a word on a 32 bit machine, obviously four bytes and on the CDC 6600, 10 characters, six bit characters. So that sucked. So I get a job at a vendor and we're building the ultimate second system. If you've ever read the Mythical Man month, right? The first system works and the second system is this overblown behemoth that often, often fails. The second system was at least 20 times more complicated than its predecessor but there wasn't any of the sort of dramatic unifying simplifications that would make that manageable, right? There was no thought to the usability or the performance of the development environment. They didn't even think about how the source code should be managed. So it really sucked. The thing was bursting at the seams. You know, the global namespace was only six characters. So you had names like PPR, RVR, that was a real name. And there were tons of other things that started with PPR because PPR was the name of the subsystem. So a lot of three character program names, variable names, it was awful. So like those predecessor operating systems, it was built around these rigid binary data structures. So, you know, an alarm was about like a circuit breaker being open that should be closed or closed that should be open or a voltage being exceeded or an under voltage occurring, you know, these different conditions. And so the data structure that defined an alarm was this array of words and there was this whole set of rules about well, if word one contains a one then word two is the RTU and word three is the point number but if word one is a seven then it's an RTU alarm instead of a point alarm. RTUs were the remotes that ran at all the substations and the generating plants. And so it just had this, you know, insanely complicated process of creating this word array of information about your alarm. And then to make matters worse they'd sold the system unfinished several times and that's okay. I mean, they didn't lie to the customers. The customers who bought it knew they were buying something that was being invented and it was enterprise stuff. So all the customers wanted modifications. So the groups assigned to the different projects started modifying the immature and incomplete software that was being produced for the core. And you can guess how that went. I mean, we made all the paper milestones within when we had to actually ship software and the project started to slip. One of the customers wanted alarm priorities. You know, that kind of makes sense, right? Some alarms are much higher priority than others. But with the binary approach about for sure, you know, all the code that cues an alarm that is now going to include that word 17 is the priority or whatever has to be released simultaneously like on the same day that you release the code to accept the priority. Like a lot of stuff has to happen. So thinking about the text insight and thinking back to UNIX, I concluded that alarms and log messages and these sorts of events and actions and stuff should be a text data structure. Something simple, like key value pairs. So if alarms were just like RTU point status, whatever and then one day a new key value pair called priority showed up and the code was written to follow the practice of having your code ignore but pass through items that doesn't understand and voila, you simplified. You can visually look at the alarm. You don't have to write a tool to interpret it. And you can, you know, even in its internal format it's just a piece of text that your eyes can read, right? And your mind can decode. You've decoupled the sending of it with the processing of it. So you can start sending priorities but you're not ready to do anything with them. So there's no, they're not implemented but they show up in the data. Have, you know, when you're first getting things going you can just direct alarms to a disfile and you can go tail the file to see what's in there. Now there is an argument against text. The argument is that in its text in favor of binary is that it's slower and that's probably true. And the second argument is size that, you know the text is gonna use more space than binary although with compression a lot of times the size of the text can be very competitive to binary. You know, look, I'm not saying that you would always use text in preference to binary like if you have a trillion temperature and pressure and wind vectors then by all means store them in a binary format. But if you expect changes in growth and new fields that probably then probably you want some kind of dynamic text format and I would look really closely at that. I became ever more convinced that I needed a language that was facile with text and didn't have long compile times between tries. This was in the late 1980s. So, you know, you're running on a, you know a decent machine might have one megabyte of memory and one million instructions per second of, you know performance, so it needed to be able to work and do work on a really small machine. I looked at Perl and I just didn't like it. I thought it was just really gross. I'd heard of the single TCL. I didn't have interactive access to the internet but I had email and so I emailed John Osterhoot of the computer science department at the University of California at Berkeley and he emailed me a copy of TCL 1.0, one file. It didn't even support reading and writing files at first not really like I showed you that exact thing you could, you could exec a program and grab its output or you could exec cat and write to a file and strings could have been contained about a new line so it was sort of workable, but it was pretty primitive. But it had a lot of what you see today. It had lists, set, proc, while, for, for each, a val, exec, split, join. It even had catch for catching errors and it was dead simple. You see strings internally and it seemed pretty good. So I started banging on it. I read the UNIX manuals for system calls and the section two and section three on the C library and I would think about, well, what, does TCL need this? What could it do with that? Oh, well, a sleep command, that's kind of cool. Sleep five, it would sleep for five seconds, okay. So I made what eventually became how TCL, those files, many additional commands and eventually server and client support for TCP sockets. Dennis Ritchie said in the early 1970s, I found this document, they published, I think it was in the Bell Systems Technical Journal. The number of UNIX installations has grown to 10 with more expected. Something that I think is really important that people don't realize is that UNIX had an app. There was something that it could do that was harder or more expensive to do without it. I thought that people just wanted it because they wanted a computing environment, but the app was TROF, the phototype setting system. Bell Labs used UNIX to format articles for the Bell Systems Technical Journal and to format their patent applications. And so I think this is a vitally important thing to recognize that the original success of UNIX wasn't just because it was a computing environment, it was because you can run TROF. Similarly, is how TCL got its first commercial customer, my employer at the time, the ones building the giant SCADA system. Some people came to me due to my reputation as a resident UNIX hack and asking if I could speed up the shell script that they had that they had estimated was gonna take 200 hours to run. And this is an extra big problem because the machines at the time until 286 running kind of primitive sucky mid 1980s UNIX would crash generally once a week. So the machine wouldn't even stay up for 200 hours. So they were like, hey, do you know, can you make this program go faster? And I'm like, sure, absolutely. Let's rewrite it in TCL and see what happens. And in a couple of hours we had it working and it was more than 40 times faster than the shell script. So it was done in like five hours. It was cleaner and bang, instant acceptance by the company. And they began to put it to use for all manner of stuff. And I think if we'd come in like, hey, here's this language we ought to use that they would have been like, whatever, buzz off or not doing that, but that it solved the problem that they had then that just completely knocked that barrier down. So I'll introduce a little more TCL now. But let me go back to the screen sharing. And as soon as I figure out how to do that, we'll continue where to go. Oh my, sorry folks. And maybe all the screen sharing we're gonna do, I'm just gonna figure out. Oh, there it is. All right, good deal. All right. So here's a proc that fetches a webpage, right? And it's pretty simple. You would actually need something fancier in, you know, if you're gonna be serious because you're gonna wanna use SSL and stuff like that, TLS. But let's look at what we do. Okay, so we're gonna set the file handle to the socket command to the host and to port 80. We're gonna send a get command and flush it. And then we're gonna read the output. And so here we're gonna try it. We're gonna try to run this proc. And here we're gonna fetch google.com slash, see if that works. Hey, oh, you know what that, there it is. Yay. All right, let's scroll up here and you can see, well, this is in a lot of stuff just for a straight up fetch slash. But anyway, there it is. Okay, that's how easy it is to get a socket open and talk to a web server and get some data, which I think is very cool. I wanted to tell you here. So I left this to remind myself. Later versions of TCL have a non recursive engine. That is it doesn't use the stack for most calls. So you can enable really, really deep recursion. It has co-routines. And as Claude mentioned, tail call, which allows you to write recursive functions that aren't recursive, because it doesn't have to return back to the caller. Here's a version of a factorial that uses tail call and we'll run it. And we get a good looking result there. All right, so we started out and we got this data. In fact, let me throw a, I'm gonna throw a little, a few slides up here for just a minute. Now I'm kind of moving to flight aware. All right, so this is the kind of the data flow of flight tracking. We have a lot of different feeds, feed from the Federal Aviation Administration and the US, from Canada, from Central America, from Australia, New Zealand and the EU and from our own network of tracking devices. We combine them all into time order and then this program called Hyperfeed processes them and tries to make sense out of it all. So, you're supposed to get a departure before when a plane takes off, but sometimes you don't. Hyperfeed will recognize that a plane so you can often generate a departure. So it kind of normalizes everything so that the downstream users can just read the control stream feed and they don't have to re-implement all the interpretation. So the downstream things like multicom, detects conditions and sends out messages and does hits, REST APIs and stuff. Bacon updates the database. Hummingbird updates statistics. BirdsEye maintains a real-time picture of what's going on. Firehose is a way that customers can receive a real-time data feed of specific pieces of the flight tracking flow. We got our first feed in 2005 called ASDI, the Aircraft Situational Display to Industry. Came from the FAA, it was made for airlines and organizations like United and FedEx that basically had flight plans and arrivals and departures and positions. And here's what some of the messages look like. They came in on a T1. It's this very ad hoc text format. There's a 44-page document that explains how it works. And this is how the air traffic control system worked in the United States. These T1s connected different centers that did air traffic control and it would send messages between the center saying, hey, FedEx 1825 is about to cross into your airspace at this location and stuff like that. It was, you know, so there was an IDENT like UAL-005 but there was no unique flight ID. And we would later figure out that there could be two UAL-5s in the air at the same time. And coupled with the lack of a unique ID, it adds a lot of complexity to the job of interpreting and understanding the feed. Feed was real-time and there was no capability to replay anything that we missed and this format was really ad hoc. This is a sample enhanced traffic management system message. At first we just ignored it. We didn't even understand it at all but inside all that is a ton of interesting and useful data about the flight and what time it's expected to arrive and what its route is and things like that. The competitors at the time didn't try to save this information and use that save information to make their stuff better and we did. So thinking about texts, thinking about all this stuff, you know, originally we would just store 20 seconds of data and process it, 20 seconds of data and process it, 20 seconds of data and process it. And then we ended up with the directory that had a million files and that was really slow and all this stuff. So I knew we had to do something better. We want to have bigger files like one file per day. And then, you know, we wanted to be able to locate a point in time in the file. So we want to be able to do binary searches on the file without reading the whole thing. And we would like it if the format wasn't too complicated and that, you know, if there was some kind of like minor file system corruption, you know, like, you know, you read a bunch of, you see a file and there's like a whole block of null bytes or something in there that you just lost that you didn't lose the whole thing, you know, like you might if it was some kind of real sophisticated self-referential structure. We wanted client programs to not have to know where the files were. So you would just say, hey, I want to read the control stream feed or hey, I want to read the FAA feed or I want to read the, you know, the Philadelphia, you know, airline feed or whatever and you just start receiving that. Clients would need to be, they wouldn't know the underlying implementation, right? We'd hide that, like I said, they don't know where the files are and then we want to abstract everything because anything that's gross that we make clients do, all of clients we're going to have to do means just writing a lot of clients. So they needed, they didn't, you know, the client shouldn't know about closing a file and opening the next one and stuff like that. We knew that there would be more feeds coming and we knew that we'd need at least one program that could read multiple feeds. And so it had to be an object, you know, there had to be a class. It couldn't just be that the program could read one feed because some programs are going to have to read a whole bunch of feeds, should be easy to set up. The format needs to be flexible and I'll show you some of that in a minute and the data needs to be able to reside on different machines because there's going to be a lot of data and we're going to fill up whole machines and stuff. And there need to be multiple versions of a feed like that we have a development version maybe that has newer software or staging version and things like that. Yeah, so the FAA feed was about a gig a day today. It's, we get over a hundred gigs of data. Seems kind of like a lot. I don't know. I know there's bigger stuff out there but we knew bigger feeds would come. We knew that we would see much larger files. You know, the maximum size in FreeBSD's file system is 2 million gigabytes. So I felt that even with large growth we wouldn't run into that limitation. ZFS came along later. It can store 16 exabytes, which I reckon to be about four billion gigabytes. So I believe it will be impossible in our lifetimes to fill up even a single ZFS file system. We had already done positional parameters. You know, we're like column one is the IDEN and column two is the ETA and column three is the estimated departure time. And we found that kind of clumsy in a real pain because it's like, oh, well I used to have seven but now I have nine and the code would be like how many are in there? Let me decide how to interpret this. XML was gaining in popularity but I felt that the markup, you know, like 20 fold, you know, it's like 20, we would see 10 to 20 bytes of markup per byte of data and that was unacceptable to me. I can't throw away 95% of the data. I mean, I can't throw away 95% of the disk space just framing the data, right? So the idea is the reader would be able to say I want this feed starting at this time, running until this time and then it just starts getting callbacks with the data. And likewise, the writer should not be concerning themselves with when to change files or whatever. The writer is just like, here's a message at a clock, here's a message at a clock, here's a message at a clock and the object that's handling the writing is like, oh, the clock changed days. Let me, you know, create the new file, point the old file to the new file, you know, with a special message that says switch to this file and now let me write the new message in the new file. So that's all done behind your back, which is super nice. X and L was too gross, positional parameters were too inflexible and I don't know what parsing is slow means right there. But so I decided that we would use flat text files and we would use tab separated key value pairs and a new line would separate each row. And then there is a distinction between live and replay, right? So a super common mode of operation would be live. That's kind of the most important thing, like I'm processing this data in real time. So if a reader is caught up to the writer and reading every row the writer writes as quickly as reasonably possible after the writer has written it and the reader should not have to do anything different when it's caught up. But there is an issue that if I'm doing a playback, right? Then, and some piece of data isn't available, I want to wait for it, right? So it's like, oh, for my data center in Dallas there's data coming, but it's a little slow over the pipe so the thing's gonna wait, you know because it wants that feed from Europe or whatever. But if I'm real time and I lose the feed from Europe I need to keep going and I need to just do the best that I can with whatever I've got. So if files were on the local machine I want to read files directly. If they're on a remote machine I don't want to have to have a service on the remote machine. So I'm gonna use SSH. So I just run secure shell and invoke the client on the remote machine and that's all done behind the back of the program. The program just says, I want this feed from this time range that software goes and figures it out and goes and gets it. That worked pretty well, I'm pretty happy with that. Let's see. So there's a local DayStream client in remote but I just said, I don't want to know. So that's cool because the universal DayStream client will figure out if it's remote and it'll use the remote thing or it'll use the local thing. This is what the TCL code looks like to define a connection. So I say, oh, I want a universal DayStream client I want to read control stream. I want to call it DS client. I want it to call my handle message function anytime it has a message. If it gets into file, I want to invoke my function called done and debug one will cause it to emit the stud error of various, hey, I'm connected. Oh, I'm connecting. Hey, I lost the connection. I'm reestablishing and stuff like that. And then I run it with parameters and then when I say follow feed async the thing becomes alive. TCL also has an event loop for like X windows that can detect mouse clicks and things like that. And in a non-windowing program I'm looking for data from sockets. I'm looking for timers and things like that. And so you can write programs that are event-driven. Kafka is a system for doing high performance cues. We like it, it's fast, it's neat, we use it. Of course we didn't have it when we started but it's also not an archival format. So you might keep a month of data in Kafka but you're not gonna keep 15 years. We also got bit using it. We found some tricky bugs and it required the Oracle JVM although I think now it works properly with the free one but I'm glad we went slow on that. Customers have come to rely on us. We have soft service level agreements. We can't break stuff. So the combiner, we started with one feed. Now we have 41. So the combiner combines the feeds. I alluded to that earlier. It tries to order the combiner, the data in ascending time order. I mean, it does order it but data can come in late and it'll be in the past and time will still try to process it. I showed this earlier, the flight tracking data flow the feeds go into the combiner. It combines into one stream, hyperfeed processes and produces this rationalized output. Why doesn't hyperfeed do the combining? Well, there's a nice separation of two things that are very different. The combining has to do all this, hey, where's my feed? Hey, I lost the feed. Hey, I got to reestablish the feed. Hyperfeed just needs to do the processing and try to figure stuff out. Feeds come and go, but hyperfeed is seriously stateful. So it maintains all sorts of stuff about all the flights that it knows about. It gets a message. It's like, what flight does this apply to? Oh, there's two, you know, which UAL-5 is this? There's two in the air at the same time. And it's nice. And then again, the combined data all in one place has just worked out to be kind of handy. I don't think I need to go into all this stuff. There's the thing about playing back. You wait for data. If you're live, you don't wait. And we also had some redundant feeds like there's two feeds from the FAA. There's two feeds from Air Inc, which is a big customer and data provider. And so we just have a de-duper object that keeps track of messages that it's seen. And so it won't send a message through twice. And that's worked out really well. The whole combiner program is only about 1,250 lines of TCL. And it's been extremely reliable. It has run times of months that are very common. They actually have a new combiner that's right in Haskell that has much higher performance, just kind of cool. We have another thing called the IP console in TCL. It's kind of neat. It's a thing, you set up an event on a socket. So if you tell that to a socket on the local host, you get a terminal session and you can interact with the interpreter while it's doing work, which is a fascinating and kind of scary thing. I mean, if you type exit, the program will exit, but it's really handy for interacting with these long-running programs. Let's see. Okay. So let's go back to the... Oh, I just ended the share and I didn't need to do that. Hang on just a sec. Oh, no, I didn't. Here's the share. Okay, we're back on the TCL stuff. So here in this window is a sort of idealized position, right? And I'll run that and I'll puree it. So a position, generally, is an identity. An altitude, latitude, longitude, a heading and a ground speed. And a clock, I missed the clock in there. And of course that you'll recognize these clocks are UNIX system time clocks. And actually, a good old TCL here is really good with that. If we say clock seconds, that's the UNIX system clock. Oh, I've got some clock stuff coming up. All right, we'll do that in a sec. So I set up this position thing. We printed it. Now I'll do, check this out. I'll say array get position and it's a list of key value pairs. So I can say array set pause to array get position and that's a copy, a complete hard copy. And then I add the pause and new value. Right here, this is, okay, so remember I just said a minute ago that a position is an altitude, a heading, a latitude and longitude, a ground speed and a clock. This is what a modern freaking position looks like from one of our data sources. There are a lot of new columns in there. The type is a position. The item is UAL 79. The reg is the actual tail number of the array. The reg is the actual tail number of the airplane. That's over here in 27965. These are actually sorted in alphabetical order just so that when you do look at one, you don't pull your hair out. Look, aircraft type is a Boeing 787-900. The air ground switch says it's in the air. The altitude in feet is 38,000. The GPS altitude is 37275. The destination is in Japan. There's a facility ID. There's a feed ID, all this crazy stuff. Just like I was saying about, you want to add priorities to alarms, they can't add these new columns and nothing breaks. Everything just handles it. And there's a lot of cool stuff in there. So here we will actually set that message into an array and we'll list it out. It's a very simple way to do it. We'll just put that in a different array nicely formatted. And all the different stuff, the origin K-E-W-R, that's Newark, R-J-A-A, I think it's Tokyo. Here we'll format the clock. So there's your standard UNIX format. Universal time. And clock is again, Oh, well, I want to do time zones, you know, and you can even do the locale and like it'll format in Japanese time and it's all UTF-8 and stuff like that. So that's pretty cool. Array size just to show you array has these little sub commands that can do things. Here's a. Now, we don't want to call functions and constantly pass arrays as lists to the function, but T cells all call by value. So we wanted to have a way to do a call by name. I wanted a way to pass the name of an array and access it in the stack frame in the caller, which is something that TCL can do with this community called Upvar. It's a little bit lame that it works this way but it has some cool stuff. So here pretty position is going to take the name of the array. It's going to alias it to a position locally and then it's going to do this pretty formatting. So here we'll say pretty position of this message. And, and it didn't copy the array it just passed it passed the reference to the array and then that's cool too because the functions can edit the array, if you want them to work that way. So what I'm going to show you on the syntax of the language is this is a call to postgres PG select. So it assumes that you're doing a select that you're going to return zero or more rows. So the syntax here PG select database handle that you've opened with PG connect to your postgres database, then your SQL code. It's got this colon message of item. And then that's like a dollar sign but it's actually we do a little SQL parse and we recognize that and do the substitution so that we guarantee that there's not going to be any quoting problem. If there's single quotes in here or whatever you're not going to get a SQL injection attack. And then, and then row the name of the array. And so it will invoke this code body repeatedly with row refilled for each result. And then what I want to say about this something that TCL has that almost no other language has which is in this code body now see PG like PG selects not part of the language right you know in a in a for loop you've got break and continue those are pretty some things to have. And so here in this code body that's executing across these things, I can execute break or continue, and I get the proper. I get the proper behavior of break and continue in a code body that's attached to a command that is not built in the TCL. And I think you're going to have, you know, I don't think that can be done in Java at all. I could be wrong, you guys are kind of, I think bigger, bigger time language hacks than I am. So, so you might be right. Okay, so I'm, I'm drawing to the conclusion here. That's that's really my my intro of TCL I want to say a couple more things. The TCL. It is amazingly quick to get software written in it. It to me has a lot of the power of list. I tried to get some list people interested in it, you know, use that groups comp playing list. And they're like, buzz off. And I was like, Well, you know, it would be good if we could get regular people to use these list like capabilities people are kind of turned off by list and they were like, Yeah, we don't care. I was kind of disappointing. A lot of people did really like it. It's, it's heyday was has probably passed, you know, it's, it's gone out of fashion. I don't think there's anything wrong with that. It's super solid as Claude was pointing to earlier, like, there's a, well he didn't mention it, but there's a gigantic test suite. We haven't had a regression in the language. There was like a memory leak and there were a couple of kind of weird things but as far as, as far as something that worked and then broke and then started working again that just that really doesn't happen there's a lot of rigor in the generation of the thing it's very solid. It's a, it's a hiring issue like a lot of people are like what's this TCL thing. Why do I have to learn that that's not going to be good for my career. I have a machine learning team that we built it internally because it's really hard to find ML people so they just started reading and experimenting and they, the guy running that was like hey, you know, Python's real popular for ML. So ML for TCL, we could code TCL interfaces to the C libraries do you want us to do that or can we use Python and I'm just like yeah use Python, I didn't want to give them this extra work. And I wasn't sure how it would be expressed as TCL so they took off and wrote a lot of good stuff with Python and a few months later the guy came to me and said you should look at Python. It's really good. I've been turned off by it with the indentation being meaningful they really hammered that into us in the programming languages class that you don't want to have space be meaningful in a program and in snowball space could actually change the meaning of a program and was kind of a problem and it's interesting to people, but I kind of use that to ignore Python and then when I started looking at it I thought it was really good and the next thing for me was to kind of feel like oh I should have looked at this a long time ago. But the prospect of rewriting, you know, 16 years of TCL code now with 70 developers was, it's impossible companies go out of business that try to rewrite so I invented a thing called tow hill, which is a really deep integration at the C level between TCL and Python. It's a, it's a Python module that you can import it's a TCL package that you can package require, and it makes it very, very seamless, almost perfectly seamless to call TCL functions from Python they look like Python functions they behave like Python functions the optional arguments work the same way. It can actually tow hill from Python can invoke TCL functions more capably and in some ways in TCL itself can and it was really amazing for about a month I was just on fire writing this like the code was writing itself and I was just the vessel, you know what I mean. If you've ever had that experience super throwing go to bed at four in the morning laying but can't sleep. Get back up work for another half an hour go back to bed, wake up at seven and go back to work so that first month was just this this fantastic feeling of creation and then the second and the third month was just grinding. You know, like, it got it got immediate use of the company they found a bunch of bugs. Thank goodness I had readopted test writing a lot of tests, because you know you would make a mistake and it will cause a crash. When you ran the test but if you didn't have the test you wouldn't realize that you had introduced some kind of weird bug because both Python and TCL have reference counting and so you know if you screw up your reference counting and Python you get a crash if you have a memory leak if you if you get a script your reference counting in TCL you get a crash or you have a memory leak so. But anyway I'm super happy with it and I've got to say that TCL. There's actually a TCL OBJ object that that is a Python object that front ends the TCL object that's behind and it's way more flexible than the normal Python objects like. Python use a TCL object as a of a numeric value in a in a you know he's a five plus some tickle object and it will perform the calculation it implements the entire number protocol it. It's just sort of amazing, you know, like in in Python you might have to say int of a string to use it in a, you know, to add it to another number right, or you might have to say stir of a of an integer to turn it into a string but with the TCL OBJ it just does the right thing and it works really well and it's got a lot of. It's got a lot of a lot of use and in ways I didn't expect so I expected that we would use Python to call TCL and of course it would be necessary for TCL to call Python, but I was surprised that the my peeps have already. There was a case where there was a real cool Python API to talk to this rust API for this software they wanted to use, but with TCL they'd have to just, you know, write it all manually and so they actually use TCL to invoke Python to talk to the remote service so I was pretty happy about that. Okay, so the last thing that I want to talk about just real briefly, I want to offer a kind of an olive branch. Between, between like imperative and functional programming. You know, I, I'm a big fan of aviation I've worked in the industry and stuff for a long time. And before flight where I even was a GR craft instruments and stuff I kind of glossed over that but I read aviation weekend space technology, cover to cover for 20 years and I don't know about about 20 years ago. NASA had discovered this laminar flow laminar flow that's that's like the flow of air that is non turbulent. And they saw, oh, laminar flow over a wing man if we could make a wing that had laminar flow like the drag would be less the lift would be higher like this could be a huge huge revolution in how you know how efficient airplanes are. So they built a model and put it in the wind tunnel and they were expecting like 40% better and they got like 6% better. And they were like why, you know why is this improvement so much less than we thought. And so they went and they went and looked. They read existing wings and they discovered that almost every successful wing of every airplane ever made was mostly laminar in the flow, even the right brothers the right flyers wing, mostly the air was laminar so they couldn't improve on it as much because it already was that way. And so, I think I think that you can tell, you know, I'm kind of in the imperative world there's a heck of a lot of state I need to know where the airplanes are I need to know what's happening at the airport I need to know what the weather is like, like, you know, life is very difficult for people right, but there is a lot of what I would call functional ish programming in the imperative programming world right regular expressions. Okay unix pipelines event driven programming, you know where my programs waiting for something to happen. It processes is that thing and when it's done it's waiting again now I'm not saying there isn't nasty state and I'm not saying it's going to produce exactly the same result because the conditions are identical. But, but my point is that that SQL like that PG select that I just showed you, you know, the point is my point is that there's way more functional ish programming going on among imperative then then we might normally think in that that gap. I know it's a big gap to make the decision that you're going to do something entirely functional, but I just think that imperative programmers are using imperative developers are using what I what I'm saying functional ish they're using a lot of the of the techniques and the approaches and and the kind of magic of functional programming in, you know, as part of their imperative just like how the wings had a lot of laminar flow to them. And so that's it. Thank you for staying with me with through all this and let me end the share here and ask if anyone's got any questions. So I just want to thank you for the talk that that was wonderful. Yeah. I was inspired, and I want to end up to what questions do people have. So Carl's show. I was curious in the flight aware of what proportion roughly of the code is actually PCL versus, you know, what else use other than Python see your Java or Okay, great. Hi, by the way. Thank you for coming. Hello, your focus here the. I would say it's probably about 90% TCL. We have my at my outlook is, you know, glass half full like I'm open, right, you know there's a cost to supporting a lot of languages, of course, like, you know, we have two guys who are really going to ask all we have a few guys who are going to Ross, we have a bunch of people are going to see plus plus. But I just I want to be open I want to be open to what's new to what's next. So there is C C plus plus rust, Python. One of the things is the community is so much larger, you know, for Python and even C plus plus and rust than for TCL so we've had to write our own interfaces to, you know, Cassandra and Kafka and a lot of different tools that have been solidly supported from Python. And the people are happy with Python and, you know, getting frameworks and stuff going and being able to do kind of the modern stuff they like but yeah it says 90% TCL still. Oh, I was going to also complain about TCL to I want I didn't want to say one thing that has been a kind of a missing is data structures like the the arrays are cool. And it does these things called dips that are a, you know, a kind of a hierarchical data structure that's pretty flexible but it's not like I mean I wanted to find a structure. I guess, you know, because it does like Claude said there's many many object systems and so yeah if you define a class and it has local variables that's kind of a data structure but I would I would like TCL to have more than it does. I can see a lot of times maybe I it doesn't have quite what you need so you end up doing something weird with up far and namespaces and stuff and anytime I find I'm doing that then I know that I'm working around a short shortfall. What I think is the shortfall language. Yeah boy you can get I mean you can be writing programs in a day in TCL and I mean pretty real programs but in Python, you're not writing anything real in a day unless you're way smarter than me. Who's next. So I'm going to piggyback on what you just said, because I didn't say in my introduction. I started learning TCL trying to say TCL people said all over the place like oh yeah you can you can get like a real program written into it in a day. And then I went to like write a GUI and at the end of the day, it worked. And I was shocked, like everyone said it but I didn't believe anyone. But it was like, Oh yeah, this works there are a couple of bugs there are a couple of you know features are missing but yeah, it was there and it worked and yeah I kind of lost my mind that it was is. Yeah, that that quick to develop. You know I didn't actually talk about the toolkit at all there's a graphical toolkit called TK that works with X windows and runs on the Mac and runs on Windows and if any of you are in Houston if you ever go to visible changes. The touch screen app that is that is a TK app 100% for sure. I was at NASA touring mission control, you know and looking at the displays through the glass window and I'm like those are TK apps and I went home and Google NASA TK and sure enough. The X windows programs were really hard to write and they're very easy and TK I did a lot of TCL training back in the day and just what Claude was saying like. Over time as I got better at it, you everybody we were just fire up wish and and we would create a button and, and, you know, the button would appear on the screen and they would click the button, you know, push the task release to detonate, or whatever. But the students would just be blown away that they could get that they could actually get GUI programs running in minutes, you know, really simple stuff but just to see that. It's just fallen by the wayside a little bit just because everybody's in the web right, or at least using WebKit for formatting and stuff. So, I'm curious about that, because just from the last time I looked at TCL, which was, you know, the 90s. It just what you showed it doesn't seem to be very discoverable. So what explains the ease, which people can get something up and running. Can you can you say more about what we mean by discoverable. So it, it looked to me when you were doing the demos. Yeah. There was no way to know what to do. That is, you had to know the command. And then you had to know the some commands, and you have to know whatever the parameters are, right. And a lot of languages make a trade off where they get complicated. And the trade off they're making is that it allows you to sort of exploratory Lee examined, you know, what you're doing like you can hit a dot in an ID, it will show you some options right. Okay, sure. Well, that's well part I mean you're right in in Jupiter makes that you're a little more helpless that if you're in the command line you can hit tab and get command completion and there isn't TSLX to help command that that will give you some documentation. But so so you're more helpless in Jupiter but it isn't you know it isn't I agree with you it's not. It's not really jumping in and trying to help and there's some really promising like Scala and stuff in the ID you know where you're a little bit like how the hell did you know to offer me that. How did you read my mind and know what I was going to type yet. Yeah, yeah. Have that now. I mean it's weird. Yeah, it's, it's a there's some of me right so now we're not, it doesn't have that and I don't think it ever is going to the main, I think, you know, like always it's like you're Googling and you're looking at examples and you're reading stack overflow postings and you're asking Claude for help and, you know, you're right but yeah yeah you're exactly right and and fortunately though the vocabulary isn't that large. And there's a guy I mean I never remember all the string suboptions but I remember there's something and I'll go read you know it's like well I know I can say string is something or, you know, I can usually remember. And then I have to dig in so you know what I mean you've got like your working memory of stuff that you can really remember like I can definitely get a file open and read it and parse it and do things but then if I'm trying to do, you know, definitely if I wanted to do tk and draw canvas or something I'm not. I don't remember how to do all that I'm going to be reading the manual and trying stuff but the other cool thing is it is interactive and I mean you can sit there and say, you know, canvas draw. And I'm like, I don't know why did it make that tag this turn it to this color grow it this way and and just see all this stuff happening which is a very, very fun thing to do. So I'll jump in here. I'm trying to think about like this first GUI app that I wrote and because I never done GUI before because I was just like no it's too complicated. I'd hired people to write GUIs for my software. And so I think basically what I did was like, I found a tutorial, I found an example, and then I just sort of modified that a bit, and it was easy enough, there's tons of documentation out there. And so when I needed something in particular, I could sort of, yeah, I could find it in the documentation. And I guess it is sort of what I'd say, like, you have a very good question here, John. I was shocked at the end of the day that I had something that worked. Like, I was totally shocked by that. But yeah, I was able to sort of take what was out there, muck around with it a little bit, do a little bit of searching on documentation. Like, I'm not someone who actually is like, my first place is Stack Overflow. My first place is the official documentation. Yeah, and I was able to create, yeah, a GUI for the first time in six hours or something. It was crazy. So yeah, I don't know if that answers your question, but yeah, I do a lot of just taking what's already there and then modifying it. And it actually works really well, like that's better than it should. A fairly successful strategy for a lot of languages. Think about the early days of JavaScript, right? You could just look at what people were doing and say, oh, I can go change that and make it what I want to do now. Not really fond of JavaScript. But in the beginning, that was very doable. Now, I mean, you look at somebody's React code and it's like, I don't know what's happening here, right? You really have to have some help with that. And it just, I'm sort of, I mean, I don't care anything about programming, we steer or anything like that. I do this for a living, right? And I'm just interested in how different languages make the tradeoffs so that people are productive. I started out in basic and then visual basic. And I put a lot of value on being able to get started and getting something done. I'm glad to hear that, John. I think all of us who do this for a living, once the shine comes off a lot, you just want to get something working and have it be solid and strong. And I hear you. And I'm kind of dealing with this too. Like, I'm not a, 15 years ago, FlightAware, we just, we were writing procs that were just emitting HTML, basically. And now, you would want to use a framework and Django and now you've got templates and, but you've got to use React or some kind of JavaScript framework. And it's just like, there's the simplicity of looping on something and just emitting table fields wrapped with the table or whatever is gone. And I need to get my head around a way to have the beauty and the interactivity of the modern stuff. But with it being as easy as it used to be, where maybe I can just say, hey, fill this with select star from order by, and it paginates and lets you pick and say how many you want to see on a page. And all that stuff is disautomated and gorgeous. And then even into some experiments I've been doing, it's like you know, with this aviation data, just a lot of times it's like, I can't, I can't just poop out the data from a column in the, in the table. Like, you know, there's all these things, you know, so I end up having to do a lot of processing, even to, to produce a field or whatever. I've got to run it through something to, to make it pretty. I've got to run it through something that's because the user might be not wanting to disclose their location. You know, just, there's so many things that affect what we end up displaying that I've, I'm a little bummed out that these templates aren't enough. So I don't know where it's going. But I do think that abstraction is everything, you know, like I was giving this argument with this friend of mine, he's really smart, but he's like, he's like, suffers too complicated. You know, there's too many bugs, things should be simpler. And I was like, well, you should look at what Alan K is doing, because he's trying to make this whole teaching, like operating system and web browser and all this stuff. But, but I think that for stuff to become simpler, the software has become more complicated. You know, you look at ZFS, right, and all the things that it does to make sure you don't lose data and you can add volumes, you know, it's a volume manager and a file system, right, built together, which I think is brilliant. But my God, it must be a million lines of code. It took him a decade to get it solid. I don't want to live without it. You know, it greater complexity in the software gives me a simpler experience. So I understand that software must get more complicated, but we need those breakthroughs like Unix was, you know, before Unix, you know, the, you interacted with the block size of the machine. If the disk had 256 byte blocks, that's what you're reading and writing. If it had 512 byte blocks, that's what you're reading and writing. If you wanted the last four bytes of the first block and the next 30 bytes of the second block, you had to fetch them and do the copying out. And Unix just gave you that array, you know, that, that just array of bytes. Oh my God, that, that was such a unifying, simplifying idea. You know, this is guys sitting around banging on a PDP 11, trying to do phototype setting and pursue their ideas. And we still don't feel, I don't feel like that's broken. And I'm not sitting here going, you know what file systems need, you know, blah, blah, blah, something I can't even think of, you know, some complexity to add in. But I, we just need people like rigorously chopping, you know, the complexity to give me something simple to get something that is really powerful. And we got to be simplifying while we're, you know, we got to be simplifying. And, and I want to, I need more of that because I'm not going to become a competent web hack and make all the beautiful stuff today. And I want to be, but I just, I don't have the capacity. So Chris has a question that chat. I don't think was addressed unless I missed it. Oh, I missed. Oh, you just asked a few minutes ago. Okay. Yeah. So it says, one of the aspects I find most interesting about the TCL system is that the proc signatures and bodies are available as text in the running system. Has FlightAware made any use of this list like dynamic, i.e. modifying things at runtime? Yeah, we've done a lot of crazy stuff. Yeah. One of the things I didn't mention is TCL has tons of introspection. So you can actually execute commands and examine the stack and you can look at who called you and who called that. And, and so yeah, you can redefine a function. So, you know, we have things that can plug a function and log when the function gets called with what its parameters are. The whole thing I was mentioning about like you can tell that into a running program and interact with the interpreter. And we used to actually even reload code into the running interpreter. So we didn't have to stop it because it was real, real staple and it took a long time to checkpoint everything. So we made, we made a ton of use of the introspection and, but we have this whole like FlightAware gadgets repo that has all these crazy, you know, all these crazy like find me, I'm not going to go look for it right now, but, but you know, like, like a ping me thing, you know, where it's like, I want to know who's calling this function. You know, I can go look at the code and see, but I need to, but, but I've looked at the code and someone's calling it and I don't know who. And so I can put this like ping me function in there and it will log like it's like a traceback, but it's not an error. It'll be like, hey, food got called from bar from snap from frame of stand, blah, blah, blah from this file, da, da, da, da, da. And you're like, oh, there it is. Okay. Yeah, it was this other package. I didn't realize it called that thing. So, so yeah, we've used the introspection a lot. I think it's terrific. And again, it's not, it's not as out of control as like, like, you know, Python has some really neat stuff with the at sign and stuff like that, but I have my head wrapped around all of it. Like there's it's so much levels of indirection and weird things. And, but also just hacks to get around that you don't want to write a bunch of methods for various data types and stuff like that. So there's some, there's some, writing that Python stuff and see, you know, there were some points where it was like, you know, if there was a way to tell what data type they wanted, that would be so cool. And, you know, it made me think more about Scala again, because you kind of can do that. Okay. That note, I'm going to stop and we'll put ever online before this. I'm going to stop now and then we can, you know, talk. Sure.