Transcript #389: More OOP for Python?
Return to episode page view on github00:00 Hello and welcome to Python Bytes where we deliver Python news and headlines directly to your earbuds.
00:04 This is episode 389 recorded June 24th. I'm Brian Okken.
00:10 And I am Michael Kennedy.
00:11 This episode is brought to you by Scout APM. Listen to their spot later in the show and check
00:16 them out by going to the show notes and clicking it. You can connect with us on Mastodon. We love
00:22 hearing from you. And if you're listening to this later, join us live every once in a while if you
00:28 want. Go to pythonbytes.fm/live to be part of the audience and it'll tell you when the next episode
00:35 is. And I'd like to say thank you to everybody that signed up for the mailing list to get our
00:42 show notes. It's nice to see that little creeping up and in listeners. And I actually find it quite
00:49 handy to find those notes later on. Absolutely. Brian, I would like to add we're coming up on a
00:55 milestone number there and I feel like we should probably do some kind of giveaway or some kind of
01:00 contest. And it'll probably happen in about the next month to six weeks. So you got to be on the
01:05 list to win the prize that we invent for the thing that we'll talk about later. So sign up.
01:10 Yeah.
01:11 Python Bytes.fm. Click on newsletter. Put your info in.
01:14 All right. Well, why don't you kick us off with it's a nice sunny day. Maybe some sort of solar
01:20 topic for...
01:21 Yes, let's do it. Let's do it. How about this, Brian, let's talk about Solara. And this one
01:27 comes to us as a recommendation from a listener. So thank you to Florian for sending this in.
01:32 Solara is a... Solara, Solara? I don't know. Tomato, tomato? Solara is a pure Python framework,
01:39 but in React style. So it is a sort of rapid application development, somewhat data science
01:46 focused front end framework or framework for building front end UIs. That's like React.
01:52 That allows you to write better Jupyter and web apps. So it does this by basically
01:59 integrating IPy widgets and other types of React based APIs, programmable like code,
02:06 not APIs you call on top of IPython widgets. So that's super cool. It can either be stuff that
02:12 runs inside notebooks that makes them better interactive things, or it can just be standalone
02:18 web apps like FastAPI or stuff like that. Yeah. Pretty neat, huh?
02:22 Yeah.
02:23 So we always need more, more UI frameworks in Python, I believe. I would put this if I was
02:29 considering Streamlit or Dash or something along those lines. It's kind of in that realm. Okay.
02:36 So let's see. It talks about the benefits of putting things together, but the most important
02:40 thing I would recommend to you is probably check out their examples to start. So let's
02:46 check out their examples. So in this area, we've got a whole bunch of different examples that don't
02:52 want to scroll. Why won't you scroll? Hold on. There we go. Now it scrolls. Yay, browser.
02:57 So let's pick one of these. Let's go to the full screen ones. These are fun.
03:01 Jesus, really doesn't like to scroll, does it? Full screen. Okay. So we've got different ones
03:06 here. You can just pull these up and let's just say the scatter one's kind of interesting. Check
03:11 this out, right? This is how this works. So you take your iPython widgets, your notebook-like
03:17 stuff, and look what you would see on the screen if you load this up. It's like a full UI. It fills
03:25 the screen here, right? And you can either upload a dataset and figure out, I don't know how to
03:28 figure out what the dataset's supposed to be, but probably a CSV or something. And then you can also
03:32 just click show me the sample data and check it out. You get this cool, interactive, probably
03:37 Plotly. Yes, Plotly UI here. And I can change the size of all these things that it works on. I can
03:45 say, I would like to see, this talks about like GDP, life expectancy by country. So I could say,
03:50 I want to see the life expectancy by country and pull that up. Continent rather, I think is how
03:58 they have data. Where's this? It was working just a minute ago. Why is this not running for me?
04:02 Maybe I made the size too weird for it. Don't know. Let's go. I guess I'm picking the wrong thing.
04:10 That's just the live demo, Chris. It just won't work. It totally is. I don't know why it's not
04:14 working. Anyway, there we go. I have to do, I just have to reverse it. There we go. This is looking
04:17 good. So you can say, show me the life expectancy by country. And then you get all these really
04:24 interesting, interactive bits. You can resize it. So this is all a super easy UI to build, Brian,
04:31 with this UI framework. That's pretty cool. And if you go back and look at the example,
04:36 they'll show you like one of the cells in a Jupyter notebook can just be this graph here.
04:41 And it has a full screen option, or it can just be like the output of a cell. It's one of these
04:46 interactive apps. How wild is that? Isn't that crazy? Yeah. And then you can also go and see,
04:52 you know, what does a tutorial look like? Somewhere. I got to go to get started. Quick
04:58 start. So if you go to the quick start, it'll show you basically how to program this stuff.
05:04 And it's, it's super easy. Just put a decorator, say this is a component and shows up in your page.
05:10 It's really focused on building these little reasonable and composable components. So it's a
05:15 little bit like shiny, actually, I think, actually. So anyway, super cool way to build these
05:20 interactive dashboards and stuff. That's more than just a picture, but a thing you can actually
05:24 play with and publish to the web. Yeah, especially I love stuff like this, like, especially if you
05:29 don't really know how you want to look at the data yet. So you can, you can give people lots of
05:35 options to. Absolutely. And it, I don't see a price. All I see is Starus on GitHub. So I think
05:42 it's just a open source project that you can use for your stuff. Not a commercial thing from what
05:47 I can tell. So one of the things I was, I was looking at this the other day, and I don't know
05:51 if you came across an answer to this question, but was it said a pure Python React style framework
05:56 for scaling Jupyter and web apps. The and is like, I was a little bit confused. Does it, do I have to
06:05 be a Jupyter type programmer to do this? Or do you know if I can? No, if you want to use FastAPI,
06:12 it can, and there's a thing called, what do they call it? A Solaris server or something like that.
06:18 So you can run that and it says, look, it'll run on FastAPI, Starlet, Flask, and so on.
06:23 Okay. I imagine you just create, just basically serve up some common template that like starts
06:30 at all, you know, those, those kinds of things. The other thing that's worth pointing out in this
06:32 whole discussion is, so this is built on top of React-on and React-on is this interesting project
06:39 here. It says it's like React for, yeah, it is. It's, it's, it's a really good logo. It's a Python
06:47 logo as the nucleus of an atom. And then a bunch of little small Python logos circling it like
06:53 electrons. That's good. So this basically lets you create code for IPython widgets that is in
06:59 the style of React. So if you go down here here, you can create, for example, a component, which
07:07 is a clickable button and you basically initialize the state and then you write the handler.
07:12 And just like the handful.
07:14 Yeah. Yeah. Yeah. That's pretty neat. And so that's what this thing is all about is creating
07:19 these little widget type things or components and then building up your UI out of it. So I say
07:24 certainly worth checking out.
07:25 I kind of want to just do one of those, like just a button that just tells you how many times
07:30 you've clicked it.
07:31 Exactly.
07:34 I'm not going to do anything.
07:36 But after it gets out, yeah, after it gets past a hundred, it'll be like, what are you doing with
07:40 your life? Leave and go do something else. Stop clicking me.
07:43 Yeah.
07:44 Yeah. People check that out. Thanks, Florian.
07:46 Next up, I want to I wanted to talk about coverage a little bit.
07:51 Think? No, I'm on the wrong page. I do want to talk about coverage.
07:56 So Ned Batchelder wrote an article called "Coverage at a Crossroads." And so there's a couple of things I wanted to point out about this.
08:05 The really so just the gist of it is it's a there's we Ned wants to make coverage.py faster.
08:14 And one of the issues is the way with the way coverage is written right now and the way it's
08:21 composed. So so he starts the conversation discussing really how coverage works.
08:28 And that's the part where I really like, even if you don't care whether coverage is fast or not,
08:32 this is a nice, fun article to realize how coverage works.
08:37 And so coverage uses a thing called a trace function.
08:40 So it takes your code and adds these trace functions to every line so that
08:44 coverage can know when any line gets hit. And then it coverage also does branch coverage.
08:49 So coverage does branch coverage with with allowing a thing called the arcs.
08:54 So it generates these four lines that look like branches, these arcs of like it could go like your line. You could go from line one to line two or line
09:04 two to line three, things like that. And so it keeps track of all that.
09:08 And and the reason why things could be faster is because, like, let's say you hit line two already.
09:15 You don't have to. And there's no branches in there or anything. It's just a line of code.
09:19 You wouldn't need to actually hit the trace function every time you hit that,
09:26 but there's no way to take it out. So there there's some ideas around making it faster.
09:32 And slipcover, for instance, has a bunch of ways. So he's taking uses a bytecode thing that there's a discussion around slipcover as a different coverage tool.
09:41 There's also discussion around sys.monitoring that came in in Python 3.12.
09:47 And with sys.monitoring, you can do something like a trace function, but it's something that you can take away later. So the idea, like, for line coverage,
09:56 this would work just great. So you could just say with sys.monitoring every time if I hit this
10:01 line, great. Now I can take that out so I don't have to worry about that line ever again.
10:06 And and then but there's there's some discussion that Ned has around how do you deal with
10:14 branching for that? And it's an interesting it's an interesting take on kind of an interesting idea.
10:21 There's an interesting problem set for how to get deal with it, kind of like maybe arcs aren't the
10:27 right way to do it. Maybe there's some other way to to deal with with branch coverage. And there's
10:32 a in it's not trivial because there's there's an example of a try finally block with a return
10:39 statement happening in the try. So you don't necessarily hit you always will hit the finally,
10:47 even with the return, but you don't know if you'll hit the line after that. You know,
10:52 you'd have to look at the code, but really fun discussion. There's a call out of where if you
10:57 want to get involved, you'd like to to offer some solutions or just help with the discussion.
11:02 There's that too. But even if you're not going to help, I think it's a cool, cool discussion
11:07 of how coverage works. And I also just wanted to thank Ned for putting time and effort into
11:14 making sure coverage is an awesome tool. So thanks, Ned. Yeah, that's pretty excellent.
11:19 And of course, there's going to be functions and branches of execution that are in some kind of
11:24 tight loop and run a million times. But after the third time, you've already realized it's 100%
11:30 covered. So if you could just because running with coverage and stuff like that, all this profiling
11:36 and coverage stuff puts a serious hurting on the performance. So if you could say, all right,
11:40 that part's done 100%, stop, stop slowing it down. That'd be cool. Yeah, I did like the this,
11:46 this, this cool idea of with the other ones of creating, like adding no op statements in
11:52 just so that for branches, so that you just like, check to see, you know, if I, if I hit that,
11:58 then that branch was taken. That's kind of a neat idea. You could, you know, add these extra little
12:02 hooks. But yeah, anyway, cool. Awesome. Awesome. Up next, thank you to Scout APM. Let me tell you
12:12 real quick about Scout APM. They're big supporters of Python bites. So we appreciate that very much.
12:19 So if you are tired of spending hours trying to find the root cause of issues impacting your
12:24 performance, then you owe it to yourself to check out Scout APM. They're a leading Python application
12:30 performance monitoring tool, APM, that helps you identify and solve performance abnormalities
12:36 faster and easier. Scout APM ties bottlenecks such as memory leaks, slow database queries,
12:41 background jobs, and the dreaded N plus one queries that you can end up if you do lazy loading in your
12:47 ORM, then you say, Oh, no, why is it so slow? Why are you doing 200 database queries for what should
12:52 be one? So you can find out things like that. And it links it back directly to source code. So you
12:56 can spend less time in the debugger and healing logs and just finding the problems and moving on.
13:01 And you'll love it because it's built for developers by developers. It makes it easy
13:05 to get set up. Seriously, you can do it in less than four minutes. So that's awesome. And the
13:10 best part is the pricing is straightforward. You only pay for the data that used with no
13:15 hidden overage fees or per seat pricing. And I just learned this, Brian, they also have,
13:21 they provide the pro version for free to all open source projects. So if you're an open source
13:27 maintainer, and you want to have Scout APM for that project, just shoot them a message or something
13:32 on their pricing page about that. So you can start your free trial and get instant insights today.
13:37 Visit Python by set of him slash Scout. The link is in your podcast player show notes as well.
13:42 And please use that link. Don't just search for them because otherwise they don't think you came
13:47 from us. And then they'd stop supporting the show. So please use our link by them by set of him
13:51 slash Scout, check them out. It really supports the show. This one, Brian comes to us from another
13:57 Brian way in the past though. This is Brian's skin that back in January said, Hey, guess what?
14:04 Pep six, nine, eight. It's been accepted. How awesome is that? And I haven't, it hasn't bubbled
14:10 to the top of my list until now, but I think it's worth talking about. This is in Python three 12.
14:16 And yeah, let's, let's check it out. So if we go over to the pep, it is an override decorator
14:23 for static typing. So, you know, some languages, C#, I think C++, but it's been a
14:29 while since I messed with it, you know, have explicit override keywords and virtual methods.
14:34 I know C++ has virtual methods. I just don't know if you indicate that you're overriding
14:38 it. Tell me, Brian, do you use the overriding keyword or you just, do you just write the
14:41 function? You just, just write it, but you can, that's what I thought. Yeah. Yeah. And in C#,
14:46 you actually say there's a virtual function in the base class, which is intended to have a
14:50 potential people overriding it. And then in the, the derived classes, you say override instead
14:56 of virtual to indicate that you have to say that right to say that you're, you're replacing this
15:00 behavior and you might need to call the base class version and all that kind of stuff. Well,
15:04 basically Python gets that if you want it as a lot of things with typing, it's multiple,
15:10 it's an optional and multiple ways. So let's jump over. If you scroll down, it's kind of weird to me.
15:15 The PEP says this PEP is here for historical reasons. It's now part of Python. So please see
15:22 override when you click it, though, it doesn't take you to the Python documentation. It takes
15:27 you a separate typing documentation for Python, but is also in the Python documentation.
15:32 Interesting. Which one wins? I don't know, but whatever the example here in the link from the
15:37 PEP is super clear. So you got a parent class and you don't say virtual because we don't have that,
15:43 but you can say at override. So the parent class, the base class has a foo function that takes no
15:50 parameters and returns an integer. I'd hear you in the child class. You say override and then as a
15:56 decorator and then foo same signature. And if you were to say override something that didn't exist,
16:01 type checking will say, there's no signature. You, your intention is to override this thing,
16:06 but it doesn't exist. Maybe, maybe you meant to type. I don't like these examples, but this is
16:12 what's written here. So here we go. You overrode foo because that existed, but you tried to override
16:18 baz, but it's bar and you misspelled it or something like that. Now I don't know what
16:23 happens if you mismatch the parameters, but you get the name, right? You know what I mean? Like
16:28 I'm overriding, it takes two parameters. Like, no, it takes one. I don't know. I have to test
16:33 that out. But anyway, if you want to have a little bit more validation in your Python typing for your
16:42 classes and your inheritance, check this out. It's part of Python. It's nothing special that you add.
16:47 It only executes at definition time for the class. So, so it's not like a runtime type thing. So it
16:53 should be low overhead. Yeah. Pretty neat. Why not use it, right? Yeah. Low overhead, high override.
17:00 High override, low overhead. That's right. There you go. All right. Well, thanks, Brian Skinn,
17:04 for sending this in. And yeah, interesting. Cool.
17:08 One of the other things that's neat is speeding up Python bits. And so there's a, there's kind
17:19 of a neat article called from Gage. Oh, that must be the group that makes this stuff. Anyway,
17:26 called "Parsing Python ASTs 20 Times Faster with Rust." So, so this, this article is talking about
17:34 speeding up a tool called TAC. Now, TAC is a CLI, says it's a CLI tool that lets you define and
17:41 enforce import boundaries between Python modules in your project. Yeah. And remember, I talked
17:46 about that a few weeks ago. Yep. Actually, right? Yeah. Episode 384, you talked about it. So,
17:52 yeah, that was just May 21st, just a couple of months ago, or last month. Nice. Anyway,
17:57 at first I'm like, okay, you sped up with Rust. We're kind of hearing that.
18:04 Why I'm calling this out, though, is that I'm not just that TAC seems cool, is that I really liked
18:11 the methodology that they're talking through here. So, they talk about not just how they made it
18:16 faster, but like the process they went to to figure out which parts. So, they used profiling,
18:25 but in specific, I think they used a tool called PySpy and SpeedScope to visualize and get flame
18:33 graphs for performance. Interesting. I've not heard of either of those. I have not, or, you know,
18:39 maybe I have, but we cover a lot of tools, man. Anyway, these look slick, but the output of it
18:48 showed that there was roughly 90% of the total time was taken by a function called get project
18:54 imports. And in that, it spent about two-thirds of the time parsing the ASTs and the remaining one
19:00 third traversing them. So, some great information and some great examples of instead of trying to
19:08 just throw rust at it to speed things up or even just, you know, using Python to optimize your own
19:14 Python, taking a look at exactly what you're doing and only speeding up the little bits that are slow,
19:22 which is, I love that aspect of this. So, okay. So, they took those bits, also went by and there's
19:31 a discussion of why the AST parsing was slow anyway, because that should have been some C code
19:39 as well. But there's a little bit of a deep dive into there, but then they jumped into just
19:49 rewriting it in Rust. And then we've covered these tools before using Py03 and Maturin to help
19:59 quickly develop some Rust for a couple functions. And yeah, so that was it. And it like went from
20:07 the example they had was a code base. It was a common code base, which was the Sentry code base,
20:14 about 3,000 lines of Python files that took like 10 seconds to test. And with this speed up,
20:23 it dropped it down to one second. So, yeah, that seems like a pretty fast speed up. So, nice.
20:30 Yeah. Yeah, it's real nice.
20:31 Also, just kind of a great user example and a short write up on using profiling to really look
20:40 at where your bottlenecks are and then maybe throwing Rust at it there.
20:44 Yeah. And it looks like they just basically re-implemented that one function in Rust and
20:49 then just used it as a dependency, right? With their Py03 extension.
20:54 Yeah. So, I totally want to try that. Like, just that'd be a great way to get into
20:58 to Rust a little bit is to just not try to make a Rust application, but just replacing
21:04 like one function or something.
21:06 This one algorithm is called a ton of times. It's super slow, relatively. It's where we spend all our time. But it's not that big, right? Like we could write it,
21:14 probably figure it out in a day or two in Rust and then off you go.
21:17 Yeah. I don't need to learn all the Rust. I just need to make this thing faster.
21:21 Tell me how to do a for loop in Rust. Tell me. Okay.
21:23 Well, tell me, Brian, you got extras?
21:27 Do I have extras? Let me check. Yeah, I do. Last, when was it? Let's go ahead. Episode 388.
21:37 That was just last week, wasn't it?
21:38 It was last week where we talked about not deleting all the repos.
21:42 Yeah. Well, one of the things I talked about was, what did I talk about? I talked about
21:48 import by string with packageutil.resolveName.
21:52 Bad on me for not doing my homework a little bit. Brett Cannon notes that discussions around this
22:00 are maybe not really great things because packageutil is deprecated or it's going to be
22:07 or something. So Brett's recommending not using packageutil, just FYI.
22:14 If it doesn't give you a deprecation warning now, it will someday. Don't go that way.
22:18 Okay. Next up, really quickly, kind of a fun thing. At the Python Language Summit,
22:27 there was a discussion, should Python adopt calendar versioning? And this kind of fun
22:34 discussion. So we have Python 3.12 right now. Should somehow it be like cal versioning? And
22:43 if we went to cal versioning, what would it be? And a fun, I think it was Carol Willing,
22:50 yeah, Carol Willing brought up that we want to at least keep our current versioning through 3.14
22:57 because then it would be the Py version. Yes. We've got to do 3.14 now.
23:02 Yeah. So a lot of this boils into a PEP 2026, which is also nice numbering because the shout
23:13 out of 2026 is when we would switch. So the idea would be what? We've got, oh, there's a table here.
23:21 3.14, no change. That comes out in 2025 if we go to this. And instead of 3.15, we just make
23:31 the 2026 version 3.26. No. Which would-- We're going to end up with a year 3K problem.
23:40 That's okay. But that's like 75 years in the future that we have to care about that.
23:46 I guess they could put a 1.26, then it'll be a thousand years. It probably doesn't matter
23:51 at that point. Oh, yeah. We can add it. Yeah. So I think we're okay. Well, actually, I'm not sure.
23:58 That would be weird, wouldn't it? I don't know. You could have 126. I think you can get to
24:03 2009, year 2099 without going too bizarrely. Yeah. Maybe we're ready for Python 4 by then.
24:11 No, we're not ready. Too soon. Too soon. So what do you think of this?
24:18 It's a little weird to me. Why not just 3.2026, 3.2027? Because to me, this doesn't communicate calendar versioning. We already have calendar versioning if you don't
24:32 care about what the number is, because it's yearly release cycles, right? 3.12 means 2024.
24:39 3.13 means 2025. And so if you're not using the calendar numbers, I know 26 is closer to 2026
24:47 than 15, but there's still-- To me, it's like, well, 16, 27. I don't know. It's just like,
24:52 here's the next year's version. Okay. I'm all for it. I think we should switch,
24:57 because I think that since we've gone to a one-year release cycle anyway,
25:03 why not somehow encode that in the number? I totally agree with that. I agree with that.
25:08 My vote's for 3.2026, like most calendar versioning things.
25:14 Oh, yeah. Just do four digits? Yeah, exactly. That's all I'm saying. Just put four digits,
25:17 so it really is the year on the end, and it's really clear that it means the year.
25:21 You don't have to know the code. That's all I'm saying. But I'm also with Carol on leaving 3.14.
25:28 Yeah. I mean, there's nothing saying, since it's bigger, there's nothing saying we could go to
25:34 two digits, and then at some point go, "Let's just throw four digits in there." Anyway. Okay.
25:40 Last thing I wanted, last extra, is Brett Cannon wrote an article called "Saying Thanks to Open
25:47 Source Maintainers." I just want to shout out, this is a really good idea. Quickly, what are our
25:54 ideas? First of all, just be nice to the maintainers. This is great advice. If you disagree
26:02 with something, be polite, be nice. It's good. Great advice. Start with being nice. Be an advocate.
26:08 You don't have to actually thank them directly, but you could advocate for the thing. So Brett's
26:12 involvement with byproject.toml, he sees other people promoting it, makes him feel good. It's a
26:17 good thing. Produce your own open source code, because maybe the maintainer might use your stuff
26:24 now. And then actually say thanks. Nothing wrong with saying thanks to people. And then there's
26:29 financial support, which is good for some projects that have open source. Ways to help fund the
26:36 maintainers, those are good too. But you don't have to fund them. You can just be nice to them,
26:40 say thanks, advocate their thing. That's good. So in that end, I kind of always forget that
26:47 Brett was involved with byproject.toml, and we might not be using it as we are today without
26:53 Brett. So thank you, Brett. I love byproject.toml. I promote it and encourage everybody to use it.
26:59 Awesome. Yeah. Thanks, Brett. Thanks to everyone. There's a lot of people I have to thank in this
27:04 community for this kind of stuff. Yeah. Do you have any extras?
27:07 I do. Let us check them out. I think I only one extra. And that is last week I talked about the
27:15 Shiny for Python Reactive Web Dashboard with Shiny. That course over at Talk Python, I said it
27:21 was going to be available soon. It is now available 100%. You can go sign up for it and take that
27:27 course. The course is completely free, no strings attached. So just click the link and take the
27:32 course if you want to learn about building interactive dashboards a little bit, actually
27:36 like the Solara stuff, but more full featured, I suppose, and a little more packaged, a little more
27:43 like Streamlit in that sense. And then also I talked about working with PyCharm to get people
27:49 six months of PyCharm Pro for free, as long as you don't already have an account that would have to
27:54 renew. With this course, you could just go to your account page after signing up for this and get
27:59 that as well. So two extras on one tab. How about that? Nice. Yeah. All right, Brian, I need you to
28:06 put yourself in like a calm and centered place for what is coming next. Okay. Are you ready?
28:12 This has been recommended to us. Oh my gosh, who sent it in? I'm so sorry, I don't have the name
28:18 here. I don't. Cohen, I believe it was. If I got it wrong, I'll correct it next time. This is the
28:25 Tao of programming. This is a big, long book here that covers many things, but I will, because we
28:33 may come back to this, right? But I want to start with book one, The Silent Void, and just read you
28:38 a few bits of it. And if you visit this webpage, folks, this is best viewed in Netscape Navigator
28:45 4.0 or older, because it's got like the digital noise background and all sorts of like, whoever
28:53 thought like this arts and craft paper was the proper background for reading, but here we are.
28:58 Oh, and it also has a frame. There's a frame inside of it. So it's just missing the blank
29:03 text. Nonetheless, here we go. Here's the introduction for the chapter. Thus spake
29:08 a master programmer. When you have learned to snatch the error code from the trap frame,
29:12 it will be your time. It'll be time for you to leave. So let me just read you a couple little
29:17 sections from this. 1.1. Something mysterious is formed, born in the silent void, waiting alone
29:23 and unmoving. It is at once still and yet in constant motion. It is the source of all programs.
29:30 I do not know its name, so I will call it the Tao of programming. If the Tao is great,
29:34 the operating system is great. If the operating system is great, the compiler is great. If the
29:39 compiler is great, then the application is great. The user is pleased and there is harmony in the
29:44 world. The Tao of programming flows far and returns on the wind of morning. Oh dear.
29:51 I think it's a little cheesy. This one's good. I like this one too. This is the last one.
29:57 The Tao gave birth to machine language. Machine language gave birth to the assembler. The
30:02 assembler gave birth to the compiler. Now there are 10,000 languages. Each language has its purpose,
30:07 however humble. Each language expresses the yin and the yang of software. Each language has its
30:13 place within the Tao. But do not program in Cobalt if you can avoid it. And Fortran and
30:19 Perl. Exactly. Anyway, this goes on and on. There's books of this stuff. People check it out.
30:24 Oh, that is fun. Nine books. Exactly. Oh, dear. Well, that's the joke for today. If you will,
30:34 it's the entertainment segment, Liz. I'm not sure it's a joke. Yeah. No, it's good. I like it.
30:39 It's the meditation section, Brian. All right. So with that, I'd like to encourage everyone out
30:48 there to send us good programming jokes because we're running dry. No, that was good. But also,
30:55 yeah, I always love good programming jokes and dad jokes all together. So keep them coming.
31:00 Yeah, they're always good. As always, really enjoyed talking with you. Enjoy talking with
31:06 everybody in the community. And yeah, keep on coding and having fun. Thanks, Michael.