C++ Club - 161. Sanitizers, Cpp2, exceptions, compilers

Episode Date: May 21, 2023

With Bjarne Stroustrup, Frances Buontempo, Gianluca Delfino, Vladimír Arnošt, Andrew Fodiman and other colleagues.Notes: https://cppclub.uk/meetings/2023/161/Video: https://youtu.be/WAhBuIhaDLM...

Transcript
Discussion (0)
Starting point is 00:00:00 Welcome everyone, this is Meeting 161 and today is the 4th of May 2023. First of all, I'm going to start with book news. C++ Book Camp got updated and got another chapter, chapter 6, Smart Pointers and Polymorphism. So this is the chapter where you learn how to program your way out of a paper bag, as Fran promised. Indeed, it's a very important skill and actually quite a nice little kind of go-to problem that I use for various showcasing various things, including some machine learning algorithms in a previous book but this one some blobs just move up the screen and some of them in fact all of them managed to escape the paper bag so we start with some basic blobs always do the same thing which is boring
Starting point is 00:01:02 but it it gets us going and then we mix in something some blobs doing some random steps so you can erase at the end yeah so you remind us when the paperback edition is coming out so i'm not a hundred percent sure it depends how long it takes me to finish writing, but certainly early next year, if not before then. I think it's scheduled for Feb next year. But one can already access partially the book on the website. Yeah, so if you buy Manning's early access programme,
Starting point is 00:01:43 you've got access to this live book, which we're looking at now. And you can leave me comments there. And several people have asked questions or suggested better ways of doing things. And you also get an e-book copy or a PDF, so you can put it on a device of your choice as well. Nice. A curious thing I noticed you are using East Const in your code examples. Oh, force of habit, yes that's a controversial one isn't it? It's one of those religious wars. Well and some people won't like the brace placement either. Yeah, I started life with East Const, and I know opinions are divided on this.
Starting point is 00:02:33 I'm a force of habit. There is no disclaimer in the book explaining why the East Const. Perhaps I should explain myself in the intro. Or go through and go West Const, or mix it up and be incoherent, which would make everyone angry. Get people used to real code. Yeah, it's best to be consistent at least per file. Yeah, yes, quite.
Starting point is 00:03:00 But I found that East Const is easier to explain for beginners to demonstrate how compiler sees it. Although I think C++ core guidelines prefer Westconst. Yeah. Fair point. Next up is a new issue of the Overload journal, 174, with Franz's editorial, The Rise and Fall of Almost Everything. And it's very interesting. There's philosophy and there's random numbers, so you should read it. The next article is Drawing a line under aligned memory by Paul Floyd. When we allocate memory, we often forget about alignment.
Starting point is 00:03:56 Paul Floyd reminds about various aligned allocation functions. Yes, I've seen this problem in production. We had a very hard-to-track bug with eigen failing because the memory supplied to it wasn't aligned once in 10,000 locations. So that was fun. Yeah, Paul Floyd does some pretty hardcore math stuff in his day job, so he knows quite a few edge cases. I'm trying to encourage him to write more things for us. He knows a lot of things. The article by Andreas Fertig, C++20 Concepts, Testing Constraint Functions. He says,
Starting point is 00:04:44 Concepts and the requires clause allow us to put constraints on functions or classes and other template constructs. Andreas Fertig gives a worked example using how to test the constraints. Another article is by Lucian Radu Teodorescu, in search of a better concurrency model. He presents current plans for concurrency in the vowel programming language, comparing them with other languages. And finally, Metaverse by T.D. Dai. And yeah, it's about Metaverse. Haven't read read it i might need to explain this slightly so observe this is april's edition so usually chris oldwood writes something more kind of general high level for the last article but every april we have a kind of april fall from well i believe
Starting point is 00:05:41 she pronounces her name tdd so you've got a test driven development all right going on there and it's usually a skiff on something current so this time she's decided to vent her fury on the metaverse and all things ai so that that's an april special every april there's something silly from TDD. Nice. It's been a tradition for a while. Nice. Right. Next, one update about the do expressions paper.
Starting point is 00:06:16 This is the proposed syntax. It's an expression that starts with do. There are curly braces, and then you do do return inside, and that has its own type, but it's not quite a lambda because it doesn't introduce a new scope. No, it does introduce a new block scope, but it does not introduce a new function scope. That's the thing. And the interesting update about it was that it was discussed in UG and there were a couple of polls. So the first poll was UG encourages more work in the direction of do expressions as presented in the proposal. And there was consensus about this. So that was good. And the second poll was, interestingly, UG prefers the result of the do expression be last statement, a la GCC statement expressions prohibiting
Starting point is 00:07:20 early return from a do expression. And that got consensus against, so I think that's also good. I like early returns and don't like artificial constraints about returning early from a function. I think Scala has a notion of the default return from a function or a block, which is the last statement. The value of the last statement is the return value. But I think it's good that we didn't get that. Next up is this paper. It's quite a long one, we're not going to go through it in its entirety. The title is Don't Look UB, Exposing Sanitizer Eliding Compiler Optimizations. And that was kind of a public service announcement, because according to this article, if you build your sanitizer builds with optimization turned on, the optimizer may remove bugs that would otherwise be detected by the sanitizers. We, for example, we build, usually build at
Starting point is 00:08:47 02 or at least 01, because otherwise running sanitized builds is very slow. And that's how the sanitizer documentation states that you should use optimization at least one, otherwise it will be too slow. But turns out that that might mask some bugs, and that's useful to know for anyone who's using sanitizers. That's a problem they have with contracts also. You have to be very careful how you specify a condition in a contract
Starting point is 00:09:36 so that it doesn't get eliminated. And there seems to be some reluctance to restrict the contract predicates to avoid this problem. But it's a well known problem. Maybe not in the context of sanitizers. So our sanitized build tests in one project, they take maybe two hours to run. And when I turned off optimizations and tried to run it, it took about two days. So that was... But it did detect quite a few problems that weren't otherwise visible. Or maybe I just should have run the sanitized tests more often. I think a lot of those problems can be detected statically. But of course, if you avoid sort of various antique programming styles, people don't. One of the bugs detected was an uninitialized Boolean variable, where Ubisan says,
Starting point is 00:11:00 well, this random value is not valid for Boolean. I guess that could have been detected by a static analyzer used before initialization. Yeah, it can. Or if you're getting really simple-minded, like the core guidelines, it will simply reject it for not having been initialized. Yeah, that's true. I mean, sometimes you just have to be simple-minded to be efficient, and it gets in the way of some cases and some old habits, but you can make the problem disappear much more easily than all this cleverness.
Starting point is 00:11:40 Yeah, I still need to turn on Clang tidy for many of our projects. This is the reddit thread about this, some examples and yeah, keep that in mind. And this is another in-depth article by Fangrui Song, who describes how sanitizer interceptors work, with lots of useful information on implementation. And yeah, that's useful to know for anyone using sanitizers. I mean, it's not necessary to use them, but it's useful to know how they work, so that it's not like... it doesn't appear to you as magic. Cpp2 spring update from Herb Sutter is the next topic. He says since the year-end mini update,
Starting point is 00:12:39 progress has continued on Cpp front. There is a link to his announcement video in CppCon 2022. He says, quote, this update covers acknowledgements and highlights of what's new in the compiler and language since last time, including simple mathematically safe and efficient chained comparisons. Named break and continue. Simple and safe quotes starts with main. User defined type including unifying all special members member functions as operator equals. Type namespace function object aliases. Header reflect.h with the start of the reflection API and the first 10 working compile-time meta functions from the proposal, p0707. Unifying functions and blocks including removing colons and equals from the for-loop syntax. There is a long list of contributors that Herb acknowledges.
Starting point is 00:13:48 And then he goes through all the updates. Now this one I really am not sure about. I mean, maybe it's me, but I've never used chained comparisons. And if you encounter something like this in code, I mean, it does look a bit confusing, doesn't it? I would agree. I would leave a bad comment on the code review. Yeah.
Starting point is 00:14:13 I mean, I guess mathematically you can do it, but why? There is a proposal by Barry Revzin chaining comparisons, which means someone needs it. Okay. Named break and continue. So you can continue to a label or break to a label. Some sort of go-to? Yeah, go-to on steroids. Go-to with extra steps. A new signature for main, which just has a single parameter args, and that's a container. So he says, quote, yes, this is really is 100% C++ under the covers.
Starting point is 00:15:10 As you see, as you can see on Godbolt compiler explorer, just nicer, in quotes. And the bullet points are the entire C++ standard library is available directly with zero thunking, zero wrapping and zero need to include or import. It's just automatically there. Convenient defaults, convenient semantics and services, and type and memory safety by default. I also listened to the CppCast episode, Cpp2 with Herb Sutter, which was published on the 31st of March 2023. And that was very interesting. Timur and Phil asked lots of interesting questions, and Herb is always interesting to listen to. For example, he says Cpp2 is to C++ as Swift is to Objective C++.
Starting point is 00:16:03 I'm not really sure about this. Does he think that Swift is based on Objective-C or it generates code in the same way? His example is that in later iterations of Objective-C there was a construct introduced, a concept introduced of ARC, automatic reference counting, which significantly reduced boilerplate code you need to write to manage memory. And that's sort of, kind of what Swift does under the wraps. But other than that, to me, Swift looks like a different language. I think he had a slide in his presentation and he was presenting comparisons of languages and some of them were just quote-unquote the evolution of a previous one, like JavaScript and TypeScript, and maybe Objective-C and Swift were also on that. So it's as a metaphor of kind of an evolution,
Starting point is 00:17:14 evolutionary step at least towards something. I suppose. I think it's a stretched metaphor. Yeah. a stretched metaphor of sorts. Yeah, he also said that TypeScript could take any JavaScript code and compile it and it would be valid, which is not the case with Swift and Objective-C. And coming back to Cpp2, the more progress it makes, the more it looks to me like a different language. I predicted that. It's inevitable.
Starting point is 00:17:56 Yeah. I can totally understand this. He says it's a personal experiment, and I'd imagine as you work on something like that, you want to modify more and more things, and so it diverges more and more from the original syntax that was supposed to be slightly better into something that's completely different. I mean, it generates C++, and Herb specifically said that he worked, he tried to make the generated code look nice, as if it was written by hand. But still the divergence is growing, it seems to me. And although he says it's just a personal experiment, there are already lots of contributors and lots of enthusiasm and big expectations. So yeah, if you read the reddit thread, there's lots of enthusiasm. Although some say that, yeah, Cpp2 just looks really ugly to me, so I guess it's a matter of taste. Or maybe, like you've already touched this thing, I think you Gianluca said that someone's
Starting point is 00:19:18 bound to not like some aspect of it. And that will be the sort of a sticking point. And if Herb is not willing to change that, then the number of people who had great expectations and then were disappointed will grow. He says it's really simple. I mean, he did say that, and that's a trigger for me. It means it's never going to be simple. It's simple for the author, I bet. But then, not only you need to know all the quirks and details of C++. You also need to know CPP2 and how that does things on top of C++ and what bugs that introduces. I mean, you're not expecting CPP2 to be completely bug free, right? Well, all new languages are advertised as being really simple. I remember when they were doing Java presentations where they were bringing the ARM, which was the document for C++ at the time, and in stage, you're ripping out out pages saying this is what you don't have to know this
Starting point is 00:20:45 is what you don't have to know this is what you don't have to know um that's sort of the model of introducing a new language you you don't have to know all of this you don't have to learn all of this you don't have to hire programmers that are experienced you can get anybody to use it because it's really simple. I'm maybe exaggerating a bit, but do you recognize that technique of getting a new language, getting interest for a new language? Yeah.
Starting point is 00:21:22 So you should expect it. This also contradicts somewhat the idea that we should be preserving a nicely formatted, nicely readable generated code. Because why would we have to bother generating nicely readable code if in the end we don't have to read it to inspect what's going on so if we do want to keep a nicely generated code it's probable because we need to actually take a look under the hood which means we kind of need to know both of the languages. I may be guessing, but I think his motivation may be that if you use Cpp2 and then it suddenly disappears for whatever reason, the experiment fails for example, you still end up with somewhat readable C++ code that it generates. I see. Apparently you can mix Cpp2 and C++ entity by entity in the same source file. That's gonna be fun. For example, he says a colon always means I'm declaring a new thing and it has no other meaning. So presumably Cpp2 parser sees those declarations as part of Cpp2 and
Starting point is 00:22:49 replaces them with the generated C++ code. Herb's proposals in the last seven years came from Cpp2 work. So I expect Cpp2 will have metaclasses before long. In the podcast, they talked about Vittorio Romeo's epoch proposal. And Herb says that it's an interesting idea, but on the other hand, he would like fewer epochs. I think he said he wants one epoch. Yeah.
Starting point is 00:23:29 Which I don't understand, you know, because if you do want to have one, then... Maybe he did mention that he wants one every 10 years or so. Once in 30 years opportunity, he said. 30 years opportunity, he said. 30 years. Because I think he meant a single epoch that he wants to introduce breaking changes into C++. Maybe reasonable,
Starting point is 00:23:54 I'm not sure, but certainly an opinion that is going to steer some emotions. Definitely. And presumably this is what he thinks about Cpp2 experiment. Yeah, that's the new epoch. Maybe. Well, we'll see. Definitely something to watch. The comment thread for the podcast is also interesting to read, also quite a
Starting point is 00:24:30 lot of enthusiasm. This Reddit post says, if exceptions were zero cost from the very beginning, would you have designed your libraries or app differently?" And the poster says, I'm an exception lover, but I don't use it as much as I would want to use it. But I've been recently thinking, if I did use exceptions as much as I wanted to, with no worries, how would i have written my code different basically they say if exceptions were zero cost i'd probably end up using them as much or maybe even more than if and else blocks or other control statements and i'm like no that's not what they were designed for.
Starting point is 00:25:28 I mean, an if-then-else is just much prettier than a try-catch-for-starters. Yeah, and you're kind of moving towards just doing go-tos at that point, trying to follow how you've ended up over here from over there. It's just like, ouchouch i'd rather not myself i think a lot of exception fear is just fear and rumors if you use them reasonably they essentially never triggers unless there's something really wrong and they are dirt cheap if you don't throw. That's what they were designed for, which leaves the problem. If you have so little memory that you can't have an exception handling mechanism without crowding out utility. But that's a different issue.
Starting point is 00:26:23 If you have a real computer, just use exceptions. That's what I do. But if you see a lot of try blocks, there's something wrong with your code. Yeah, this is also the consensus of the thread in general, I think. Also, there's been some measurements about what they cost and very often people forget that if you don't have exceptions, you get a lot of ifs and elses or you get these fancy features for dealing with errors which hides the ifs and eles, you get multiple threads anyway. So yeah, in most cases don't worry about the cost of exceptions, but don't throw thousands of exceptions in quick succession either, as was the case in one of the benchmarks that decided
Starting point is 00:27:17 that exceptions were very bad because a thread throwing thousands of exceptions in a quick succession was slow. Yeah, I can be slow in many, many ways. How about a near infinite loop doing essentially nothing? Or we had a case where C++ code interfacing with Java code appeared to be very slow because Java code used exceptions for flow control. So that was also misplaced blame. I mean, look, one of the things that was said very early on with exceptions was they are not for flow control. We are not using them to terminate loops. This is not Algorand 68.
Starting point is 00:28:09 This was found to be a really bad idea 40 years ago. I think we have a marketing issue here. Exceptions at BetPR. And then you have people littering their code with a noexcept, turning exceptions into terminate. Obviously, embedded platforms are a special case when there's no heap or there are hard no throw requirements. So I can sort of understand that. Hard no-throw is rare, actually. But if the implementation mechanisms for exceptions crowd out functionality, or if error handling has time constraints,
Starting point is 00:28:57 those are the places where you start worrying about exceptions. Microsoft has published an article titled Modern C++ best practices for exception and error handling. And the first chapter in big letters is use exceptions for exceptional code. So yeah, worth reading that. I wonder who wrote it. It's not original. It doesn't say who is the original author. Yeah, 8 contributors.
Starting point is 00:29:40 Right. Some compiler news now. GCC 13.1 was released. This is the announcement. And it says, quote, the C frontend got support for several C23 features. The C++ frontend for C++23 features. The C++ standard library experimental support for C++20 and C++23 was enhanced. So, C++20 is still considered experimental in this GCC version. There's still no modules, although there is some progress, apparently.
Starting point is 00:30:27 And I'm not sure about format. There was an announcement earlier that this version, version 13, was supposed to get C++20's format support. So maybe it is in... I haven't checked actually but if not you can always use the excellent
Starting point is 00:30:50 FMT library from Viktor Zverovich it's really nice okay next up is an article by Chris Wellens titled my favorite C compiler flags during development.
Starting point is 00:31:08 I realize it's not strictly C++, but the flags are pretty much similar. So I think it's relevant. He starts with this quote. The major compilers have an enormous number of knobs, which is true. There's lots of switches and parameters to customize. He proposes a few useful warnings to enable, and luckily also not only for GCC and Clang, but also for MSVC, which is really useful. And obviously a similar baseline for MSVC to WALL and W-EXTRA is compiling your code at warning level 4. I remember I had to fix an enormous amount of warnings before switching from level 3 to level 4.
Starting point is 00:32:11 And if you enable all, then this STL doesn't compile in MSVC, so level 4 is the best you can do at the moment. So yeah, very useful article that you can use his suggestions right away. And discussions of this article on Hacker News and C programming subreddit, which also have lots of good suggestions. Right, next up is Matchit, a lightweight header-only pattern matching library for C++ 17 with macro-free APIs. As we're all waiting for pattern matching to land in C++ 26 hopefully. I guess if you are eager to use matching, you can use this library. I think it... oh, right, it has an Apache license, which is permissive, and it supports Linux, Windows and Mac OS.
Starting point is 00:33:26 Is there an example? Yeah, I'm just scrolling to it. I think there are quite a few. So this is one example. There is a function match that has sort of two sets of parentheses. One is the first one, you enclose the variable that you're matching. And the second one contains patterns
Starting point is 00:33:54 with some weird syntax, including pipe symbol. And they look quite readable, I would say. And there are facilities for more advanced matching. Like you can match by class name or by type or by value. This is where I have a question. Look at that as circle, as square. Do they check them one at a time? Or do they do a virtual core?
Starting point is 00:34:30 Building things like this, and they ran very slow, they look pretty. But you get in tests, and they're dynamic tests. I think it's done dynamically. The author says Oclass's dynamic cast is used by default for the as pattern, but there are some customization points. It's reasonable. If there's 50 alternatives, you've just done a major, major hit on your performance. This is easy to do. I had students do it 15 years ago, but I rejected it for cost. Right. Yeah. There is an article in the same repository that illustrates,
Starting point is 00:35:21 it compares this library to a pattern matching proposal. And there is also another article that compares this to the rust pattern matching. So yeah, maybe as an experiment, or if you do some benchmarks for your own use, maybe you could use it. It looks familiar to Lex and Yak, a long time ago, that I used to see, like this pipe. Yeah, pipe is appearing in more and more proposals these days, even like some sort of a pipe operator. There are things like matching tuples, matching variants, matching polymorphic types, which happens dynamically as we just saw. Evaluating expression trees even. So I suspect you can write a very complex matcher that probably can run some program.
Starting point is 00:36:29 There are wildcards and yeah, so it's quite an extensive set of matching available for this library. Together with a student wrote a pattern matching system a long time ago. It was littered with macros, but it had the interest in property that it ran as fast as Haskell and other languages like that where it built into the compiler. It doesn't seem to be that a lot of these proposals actually worry too much about portability and they don't worry too much about integration
Starting point is 00:37:06 with the rest of the language. This creates a problem because people who are interested in the whole language and more than one thing don't have as much time as entusiasts for a particular proposal. Yeah. I wonder how things are with the actual pattern matching proposal by Michael Park. I haven't heard much.
Starting point is 00:37:39 Right. Next up is Clang 16 documentation. It was just released and there's a link to some C++ changes. C++ 20 features got supported, some of them. Some bug fixes for C++ 20 features. And I think Clang has more advanced support for C++ modules than GCC at this time. Right, so this is LVM 15 release. And this is the reddit thread. There is an interesting built-in function in Clang 15 starting with clang... no, it started earlier, but in clang 15 it got a nice update and it's called double underscore built-in underscore dump
Starting point is 00:38:34 underscore struct. So this is a useful debugging feature where you can pass a structure and a function to print it, like printf, and it will output all the structure variables and values, which is the go-to library for networking, because yeah, standard networking is probably not coming anytime soon. Interestingly this Boost release and the next 183 will be the last releases offering C++ 03 support for many of the libraries. About time, I'd say. And the related article, the related post on Reddit. Has Boost lost its charm i mean charm is probably not the right word but if you need it
Starting point is 00:39:48 you can use it it's got lots of useful stuff but also be prepared to pull in like a ton of other stuff that you don't use if you use just one thing and that's part of the problem once you've pulled it in you find that somebody in the organization will use the bits that you weren't planning to use. Yeah. A quote from the thread. Since C++11, Boost has shifted from provide actually useful basic containers because the STL is shit, to provide cool quality stuff that is widely useful but out of scope for the STL. See things like flyweight, spirit, log, multi-precision, safe integer, ASIO. Boost is still a wonderful library collection. So, yeah. This is an interesting article called a general overview of what happens before main.
Starting point is 00:40:53 It's a low-level explanation of how a C or C++ program's life begins before the main function is called. And this is especially useful for those working with embedded platforms, but is also interesting to know for any C++ programmer. What happens before the start function is called? That is, the start is the entry point and before main it's called before main. And there was also a talk by Matt Godbolt called in CppCon 2018 called the bits between the bits how we get to main. It a very good talk. That's pretty much all his talks. Next is a lighter topic. Dan Potts writes on Mastodon, quote, This is your periodic reminder that 10 years ago an audiophile forum started debating which versions of memcopy
Starting point is 00:42:06 had the highest sound quality. And that C++ new sounds better than malloc. Is this for real? Yeah, apparently. I went to the forum and this is the post. one of the posts, it's like a long thread. This one says, playing WAV files from a RAM disk gave best sound, then moved on to memory play. Initially, sound quality was worse. Found that the function called memcpy was the culprit. Most memory players use memcpy, and this is one of the reasons why memory play sounds worse, like digital sounding. Fortunately, there is an optimized version. Using this version removes the hard edge produced by memcpy. Also, most players use malloc to get memory, while new is the C++ method and sounds better.
Starting point is 00:43:07 A dimly related topic. I remember somebody giving a lightning talk at a conference years ago, and they transformed the compiled output, I think it was, from various different programming languages or just the text of the code into the sounds somehow and just played all these noises at us and the audience had to guess which programming language it had originated from from all these weird beeps and we actually got it right sometimes i can't remember how they'd encoded it, but that was good fun. The very long ones was probably a template error. I remember someone came up with this debugging technique, I think, in the iOS programming, which sometimes is difficult to attach debugger to or something. So they came up
Starting point is 00:44:02 with a technique where they played a sound in some places and different sounds gave you different diagnostics that you could guess. But this is just something else. I mean, I didn't even suspect that Nihu sounded better than MemCopy and Malik. I guess it's a question for Timur. He used to work in audio world. And I mean, I think it also makes fun of, you know, some of the audio fidelity people also are, you know, sometimes known for being pedantic or crazy about stuff that doesn't always exist. Sometimes, yes.
Starting point is 00:44:47 There could be software with the audio quality. Like if your hardware is of such poor build that there is electromagnetic interference actually going out of your speakers, then using different code sequences actually may affect this noise. So yeah, but I would suggest using a bare-shielded equipment rather than changing your code. If you want something of the same, go to Amazon
Starting point is 00:45:15 and read reviews of the audiophile cables, audio cables, with deoxygenated copper wires or something, and wires trained on classical music. So one wire costs about $7,000, I think. And one of the first reviews was like, someone said, when I bought this cable and played my music through it I heard angels singing to me
Starting point is 00:45:52 anyway interestingly also discussing ethernet cables like copper free network cables for network streaming and the quality of the digital data yeah it's totally bonkers for the classic network cables for network streaming and the quality of the digital data. Yeah, it's totally bonkers.
Starting point is 00:46:07 For the classic music, the voltage is also very important. They have the spatial voltage stabilizer to make sure the sound action. It's very expensive though, for the amplifier. Of course. I remember the blind test where audiophiles were exposed to music played through very expensive copper wires, and the other one was played via a coat hanger, and no one could feel any difference. But in this case, actually someone came up with a plausible reason for this. Someone says, quote, I'm disappointed by the arrogance of users on this forum. I've never had great luck being 100% confident about the behavior of code without running it. But in this case, reading the actual code posted will show you that using a bad mem
Starting point is 00:47:03 copy could have potentially caused a problem with audio quality. TLDR, bytes are bytes, but the link to post is actually about latency, not data integrity. I think it was about the feel of the sound, not... I mean, an audio file exposed to chopped up sound would probably end the experiment right there. But I think the original forum was exactly about the supposed better sounding, warmer sounding Operator New. Anyway. Right, the last one is from Mastodon. it's by Isaac Freeman, quote. The worst thing that ever happened in software engineering was when Kirk asked Scotty how
Starting point is 00:47:52 long something would take and Scotty said 30 minutes and Kirk said you've got five and Scotty got it done in five and depressionable children watched this and grew up to become managers. Right, I think that's it for today. Thank you very much for coming and and grew up to become managers. Right. I think that's it for today. Thank you very much for coming. And I'll talk to you soon. Bye-bye. Thank you very much.
Starting point is 00:48:10 Thanks. Thank you. Thank you.

There aren't comments yet for this episode. Click on any sentence in the transcript to leave a comment.