C++ Club - WG21 October mailing (cont.), fast math

Episode Date: November 25, 2022

With Gianluca Delfino, David Laks, Vladimír Arnošt and other colleagues.Notes: https://cppclub.uk/meetings/2022/156/Video: https://youtu.be/8MbJ-6pSPac...

Transcript
Discussion (0)
Starting point is 00:00:00 So welcome everyone, this is meeting 156 and today's the 10th of November 2022. We haven't quite managed to discuss all the papers from the October mailing last time, so I thought I'd come back to the mailing and see what's interesting. Mostly for me it's papers at revision zero, which means the new stuff. But I will start with a piece of feedback about a paper that we've discussed previously, which was C++ is the next C++. The paper was about introducing kind of dialects. Well, not really, but it's about introducing an attribute to your source code that would allow you to turn on particular subsets of C++ based on C++ core guidelines for different parts of your code in order to gradually improve it and make it conform to the core guidelines. The discussion on Reddit about this paper kind of exploded.
Starting point is 00:01:11 It's not often that you see 947 upvotes. Not on the Cpp subreddit anyway. But curiously, from what I read in the thread it looks to me like most commenters didn't actually read the paper but are responding to the catchy title instead they are kind of responding to the enthusiasm feeling I think there is a lot of
Starting point is 00:01:38 C++ programmers that really want to keep doing C++ so I mean it's a happy response or a happy response for a happy title, I think. Yeah, yeah. This comment, though, caught my eye. The discussion veered into carbon and related stuff. And this Redditor writes, And to this, a Redditor, Berlin replies, quote, that's not quite right, but it's fine enough. I was the relevant VP in charge of this stuff at the time of Carbon being created, and for
Starting point is 00:02:32 almost a decade overall. That particular piece is no longer in my world, but they are still very close. Carbon is definitely an experiment. It's an experiment that is public so that we can collaborate with other folks who have a similar find and see where we get But Google also has problems only a few others may have
Starting point is 00:02:56 We have literally billions of lines of C++ So for example, anything that replaces C++ must have good enough integration capability, either built by us or not, that we do not slow down productivity of the almost 100,000 internal developers. You also can't slow down Google code by a meaningful amount. Even taking a small percent hit would cost a lot. So we are figuring out what can be done and have in fact experimented with several languages to see how far we can take
Starting point is 00:03:33 integration performance etc. Carbon is essentially a backstop. If we can't do it with some existing thing, like Rust, Go, whatever, we still need to be able to evolve things enough that it's not as horrible as it is now. Horrible in the memory, safety, etc. aspects. C++ is not that bad in lots of ways. Google spent many many many many many years pushing on C++ as part of the committee. Plenty of modern C++ came from Google proposals, and lots of others as well, obviously. But that seems to have reached somewhat of an end in terms of divergence between
Starting point is 00:04:14 where we and several others feel like C++ needs to be, and where others think it needs to be. The only way to resolve that at some point is to try it out and see where you get. That's carbon." I thought that was an interesting insight in the motivation of carbon and the expectations of Google in that regard. It does seem like after the Titus Winter talk about the breaking of the ABI, this is indeed maybe a necessary tangent. We'll see where this gets to. But I'm sure we learned something from this experiment at the very least.
Starting point is 00:05:03 Yes. It's curious that he explicitly mentioned the divergence of Google's expectations of C++ and the committee, kind of confirming by that the initial motivation for this experiment. Right, so the next paper I wanted to look at is revision 0, and it's called A Plan for Better Template Metaprogramming Facilities in C++ 26. It's by Korenchin-Jabot, Pablo Halpern, John Lekos, Alistair Meredith, Joshua Byrne, and Gaj Perashman. This paper outlines big plans for improving metaprogramming, and it lists several tiers for proposals. Tier 1 is pack indexing, member pack, pack aliases, unpacking structure types, constexpr structured bindings, static assert false,
Starting point is 00:06:06 constexpr pack ternary, and expansion statements. And tier 2, lots of other mostly pack-related proposals. Some of the proposals already have been submitted, and some of them were submitted as new in this mailing. There is also a tier 3 and tier 4 which is not proposed at the moment. So as an implementation example, this paper uses the language Circle, which is Sean Baxter's fork of C++, I would say. Sean Baxter says, Circle is a new C++ compiler. It's written from scratch and designed for easy extension. Sean keeps implementing papers before they are adopted into C++,
Starting point is 00:06:59 which makes it kind of not really C++ at the moment. But on the other hand, it gives an ability to check how certain proposals work in real-life scenarios. Although I don't think many people use Circle, but Sean Baxter definitely is very active. I mean, I don't know where he finds the time to do all of this but that it's an amazing piece of work I really wish I had more experience with this it does sound like a very interesting piece of work I mean I think there is also a Circle compiler on Godbolt isn in there. Oh, I didn't know that. I should check it out. I don't know for sure myself.
Starting point is 00:07:49 But yeah, lots of stuff that is out there is implemented in Circle. It sounds really, really good. At the very least, it's an experiment. He says, because Circle is so easy to extend, I've gone ahead and implemented some of the most promising WG21 proposals for the C++23 timeframe. And that includes things like pattern matching using is and as, deducing this, universal template parameters, std embed, and so on.
Starting point is 00:08:21 I think it only supports Linux. On the other hand, it's understandable that he doesn't have time to support Microsoft's Windows as well. So back to the paper. There were some examples of what they want to do. They start with not a paradigm shift. Quote, the C++ committee likes big, bold, complex, and paradigm-shifting proposals like concepts and reflection. This is no such proposal. They want iterative improvements, and they say this paper touches on pack handling, template-template parameters, type deduction, diagnostics, constexpr features, etc. And many features proposed already have implementation experience. They say we should strive to standardize many of these individual features for C++ 26.
Starting point is 00:09:17 It overlaps with reflection somewhat, but the paper is orthogonal to reflection and it doesn't intend to compete with reflection features. In this mailing there are two papers that were mentioned in this. The first one is PAC indexing. The short version, they say, is that PACs are sequences of types expressions and indexing is a fundamental operation on sequences. So they want to be able to do that without relying on other metaprogramming libraries such as MP11 and Boost HANA to extract the nth element of a pack. Ah, this is interesting.
Starting point is 00:09:56 So this is what they propose. You just say t... and then subscript, and and so on so this kind of does feel natural and yeah i think and this is the same as in hana i never used hana i don't know i've never used it either but uh i'm sure that this must be simpler than using a third-party library. Definitely. They give an example of a meta index reference using a dollar sign, which I'm sure will conflict with some other papers. But the essence is that you can specify a type that is, for example, first from the end by referring to the end of the pack by using this special symbol.
Starting point is 00:10:43 It does look like a regex kind of syntax. Like at the beginning, you have the character, at the end you have the color. I think that's kind of where this is going. Yeah, the dollar sign definitely feels like a regex-type alias for the end of the pack. And the caret, I think they may have made a typo, because did they really mean to say the caret1 is first from the end element? Or I would have thought that it was
Starting point is 00:11:15 from the beginning. Yeah, now that you mentioned, I don't know, maybe... Or maybe they just propose a different syntax for this? Why would we need to put the caret from the beginning? Why couldn't we just use one? True that. But so these are two possibilities? The two lines do exactly the same? Well, it would make sense because they call it bar anyway. Oh yeah, the previous paragraph says C sharp uses caret to mean from the end. There you go.
Starting point is 00:11:45 So that explains things. Right. So yeah, this looks like a good thing to have for pack management and manipulation. And the second paper was syntax choices for generalized pack declaration and usage. This is by Barry Revzin. The goal is to allow declaring packs in more places, allow more functionality for packs, like indexing and slicing, and allow more functionality
Starting point is 00:12:17 for tuples, indexing and unpacking. I think we've seen some related proposal earlier by Barry, which was about structured bindings that can introduce a pack. And there was some problem with dealing with packs outside the template context. I think this paper proposes to enable that, so that you could use packs everywhere, where you want. So yeah, lots more of... everywhere. Oh yeah, the paragraph 2.2 says packs outside of templates. That definitely rings a bell. So yeah that would be a good start for this paper that improves metaprogramming.
Starting point is 00:13:11 Next one is by Niko Yosotis. It's titled Final fix of broken range-based for loop revision 0. The issue, he says, is a bug that is 13 years old now, applies to one of the most important control structures of modern C++, and leads to confusion and ill-formed programs due to unexpected undefined behavior. The gist of it is that if you have a range for loop and you have more than one function call on the right, you run a good chance of ending up with a dangling reference. I think he proposed a fix earlier. The paper was P2012, and the title was Fix the Range-Based For Loop. I think the essence of the fix was to introduce a new paragraph to the standard.
Starting point is 00:14:04 In the paragraph Temporary Objects to the standard. In the paragraph temporary objects in the standard, he proposes to, instead of, say, there are three contexts in which temporaries are destroyed at a different point than the end of the full expression, he proposes to make it four. And the fourth context, quote, is when a temporary object is created in the for range initializer of a range-based for statement. Such a temporary object persists until the completion of the statement.
Starting point is 00:14:34 End quote. So it would basically be a hard-hoc fix just for the for loops. It wouldn't generally change the rest of the rules for the lifetime extension of temporaries, you just say for loops must work and then it's up to the compilers to make it work. Essentially, yes. That's my understanding. And this was rejected because, as I remember,
Starting point is 00:14:56 the committee wanted a more general solution and not just a fix to the standard that's specific to for loops. Since nothing of that kind was available, and still isn't, Nikolai Yosutis says maybe let's go with what we have, because otherwise this situation will keep producing undefined behavior. There is some updated wording to the standard that is proposed in this paper, but the essence is the same, that there is a false context where a temporary object is sort of preserved until the end of that loop. Yeah, I'm kind of curious how this will go this time, because I think the current solution to this is mainly to tell people, well, don't use more than one expression on the right side. That's not ideal. I mean, it's kind of tricky.
Starting point is 00:15:52 How do you do it? I think this kind of stems from the fact that if you look at CPP inside, when you write a for loop, a for range, then this gets expanded in a way that whenever you have a temporary there and you add another temporary on top then this gives you the first one gets destroyed in the process yeah so i mean it is probably affecting mostly this the full range but maybe there's some other cases that this also appears and it should be fixed so i don't know. Fixing it in this way, I do question if somebody would come up with, okay, so what about that in this other case where this similarly happens? Yes, that's true. That's a good point. Also, I just thought that if this is fixed,
Starting point is 00:16:42 then by upgrading the compiler, you change the behavior of the existing code, which may also be a problem. I mean, yeah, potentially, yes. Somebody would argue, okay, maybe that code before was broken and now it's fixed, so changing it would be fine. Yeah. But this is, I don't know. I'm looking forward to see what the committee thinks about this.
Starting point is 00:17:04 I'm really interested. I mean, I agree. It's kind of a problem because it seems like we want to make it easy to do for loops. And then we introduce this subtle catch. But it does look like one of the many subtle catches we have in C++. And I don't know how to fix this. Yeah. I don't know how to fix this. Next one is a fundamental paper, C++ Ecosystem International Standard.
Starting point is 00:17:34 Quote, we propose to publish an international standard that specifies formats, processes, definitions, and so on that facilitates the interoperation of the tools and systems that implement and interface with the C++ international standard. So this seems to be about enabling tools to interoperate in a defined manner. They say users should be able to mix and match their preferred build systems, compilers, linkers, package managers, static analyzers, runtime analyzers, debuggers, profilers, etc. without needing the tools to have vendor-specific knowledge of each other. Vendors should be able to focus on direct tool improvements rather than figuring out
Starting point is 00:18:23 how to interact with yet another proprietary interface. I think it's a very noble goal which will probably be near to impossible to achieve. It seems like one of those things that if you don't impose from the beginning then to retrofit it into the whole thing it's going gonna be at very least bike-shedded into your oblivion. But yeah, I mean, it would be a great thing to have. I seem to remember there were some proposals to standardize parts of this, like for example, a description of the library dependencies or module dependencies, so that the work of build systems is easier a bit. But this one is more general.
Starting point is 00:19:18 Hmm, interoperable tools. What a concept. No one's done that before. The next paper is Last Use Optimization. This one says, In previous C++ standard versions, more and more optimizations of return values have been added, with acronyms like RVO and NRVO. These optimizations reduce the number of copy constructions and move constructions occurring
Starting point is 00:19:51 in return statements by not performing copy and move operations exactly as it seems from the source code. This proposal generalizes these rules to any code where the compiler can prove that a value used as argument of a function call is not going to be used after the function returns regardless of how control flows. This includes the cases where you today correctly wrote stdforward and stdmove, but also the places where you forgot to do so. In summary, the values considered are localByVvalue variables, by-value parameters, r-value
Starting point is 00:20:29 reference parameters, local references referring to local variables which contain last used values, dereferenced local pointers which can be proven to point at local variables which contain last used values, and non-static data members inside are value-qualified functions. So this seems to propose more compiler magic to enable it to figure out if a particular variable was going to be used past some point, figuring out the last use, enabling more optimizations without you doing anything additional. So that's probably good. I mean, yeah, like the example is very explicative. This pushback of row, which could in principle be moved,
Starting point is 00:21:17 I guess. Yeah, yeah. If that would be possible to catch and optimize, then why not? I do wonder if there is instances where this happens and he wants to make it standard so that it would be
Starting point is 00:21:31 happening all the time or if so far this never happens because it's too difficult to implement. I don't know. Yeah, I'm not sure. I think it's about more about the things that are not happening at the moment, and cannot happen because of some restrictions, but could happen if the compiler
Starting point is 00:21:55 could figure out that this was the last use. Right, next paper is role-based parameter passing by Bengt Gustafsson. Quote, this proposal introduces a way to get a role-based parameter passing style similar to Herb Sutter's ideas in D0708. And my impression is that it's influenced by what Cpp2 does, or automatic parameter handling like in Carbon. I think it's about adding some annotations. I'm not sure how to... Yeah, so it's like a prefix, forward space, and then type, and then variable name. It introduces a set of types and annotations like in or ref.
Starting point is 00:22:50 What's floats? I think you define these floats above as a combination of two. Oh, right. There is a little bit more to this. Like you can also combine things into some sort of packed version of the parameters. Oh, so you write floats and it generates both doubles and floats? I don't know. But if you go back up, maybe there was something there.
Starting point is 00:23:17 It does sound like a lot of stuff on the plate for this proposal, both the annotation and this way of backing. Yeah. Those floats appear like out of nowhere. All the way, I think. All the way, all the way, all the way to the top. All the way to the top. Okay.
Starting point is 00:23:35 Oh, yes. Yes, I missed it. Typeset floats. Yeah. Float double, const long double. Okay. Got it. So I think you get like some sort of struct that contains those types.
Starting point is 00:23:48 Oh yeah, there's another interesting syntax. A typeset of one can be used to disable the universal reference aspect of templated parameters, and they include treff or treff in angle brackets, right in the parameter list of the function. That's weird. There's a lot of stuff going on in this paper. Yes. Okay, leave it for now. Right, this one's interesting. Non-transient constexpr allocation. I think we mentioned this before. This is about allocating memory in constexpr expression and continue to use it at runtime, which seems like magic. But actually, I think from what I briefly read, the compiler will place this allocated memory into the static data segment. And the
Starting point is 00:24:41 problem then becomes to tell the compiler somehow that this memory should not be freed. So it's like you allocate it as you wish within a constexpr function, like here, like new unique ptr, new int, and so on. But instead of doing dynamic allocations, the compiler will allocate this memory in a static data segment of the program. But can you also do it for vector? How does that grow? He does mention allocating vectors. Some cases are rejected, like nested unique ptr. He says, how can the compiler distinguish between a mutable object that is read during constant destruction? I think I answered my question of this fact that this would be constexpr and so it wouldn't have to grow.
Starting point is 00:25:38 Yeah, that's probably true. He proposes a new standard function, std mark immutable if constexpr. That was proposed in another paper, that was removed. Another keyword, possibly, propconst, which was also proposed by another paper. A new qualifier, he says, that would propagate constness of the object through the pointer. Ah, I think the problem is that constexpr const objects don't propagate constness of the object through the pointer. Ah, I think the problem is that constexpr const objects don't propagate constness, so you would end up with something allocated in an immutable segment of a program but wasn't marked as constant. The idea is interesting, but the implementation kind of
Starting point is 00:26:26 grows a lot of workarounds around it. Yeah. I don't know. I'll watch this one. Definitely. Okay, so this one returns. Exploring the design space for a pipeline operator
Starting point is 00:26:42 by Barry Revzin, who proposed this previously. He says a previous paper proposed a new non-overloadable binary operator pipe greater than such that the expression x pipe greater than or right arrow if you squint. How do you say it? X goes to F of Y was defined to be evaluated as F of X and Y without any intermediate F of Y expression. And he explores various designs like left threading, inverted invocation, placeholder, language bind, so on. This would enable writing fluent statements like using arrows. And even more so, if you see here, if you use a font that has ligatures, which most programming fonts do these days, you
Starting point is 00:27:46 get a nice triangle, like an arrow. I'm sure he had that in mind. This is a little bit like piping in ranges, but just for functions. This is probably going to be more difficult to get in, I think, because it does look a little novel. Yeah, and it's failed previously, so that doesn't bode well for it. But kudos to Barry Revzin for not letting it go. Oh, he's keeping busy. Keeping at it. Yeah. Well, it sounds like syntax sugar to me, but if actually that function f was a method of a class,
Starting point is 00:28:30 then this is identical just to calling a method, which on the left side, it would be the this pointer or the instance dot function. That's basically just the same as calling ordinary methods where the this pointer is actually the first hidden parameter, it's just not explicitly mentioned. So I wonder if he actually mentions intents have to be a freestanding function? I don't know. Actually, that rings a bell. I think his first attempt was about enabling sort of a universal function call syntax in C++, which went nowhere as a proposal. But by using this, he wanted to kind of sneakily bring that into the language.
Starting point is 00:29:17 And I think your point about it possibly being a member function call is a good one. I think that might be his goal. Although I'm wondering what kind of problem is this a solution for? Nice arrows in your code. I think, yeah, it's mostly solving the same kind of problem that the pipe to mix the ranges solves. Instead of having to write things nested into one another, you have this progression of these and these and then going to that. So you write things in the way that
Starting point is 00:29:52 you naturally would write instead of nesting them backwards. Now if this provides as much value as the piping of the ranges, I don't know but I think that's where this is going. It is syntax sugar, I think. Maybe this will work together with coroutines and enable easy asynchronous pipelines without having to use ranges or something like that. I don't know. Right, so the next paper is the Val object model. Quote, this paper presents a low-level programming model that is simple, powerful, efficient and safe. We believe it could form the basis of a future safe
Starting point is 00:30:39 dialect of C++. This is less explicit than CPP2 and Carbon, but still, VAL I think is a new proposed language by Adobe Labs, judging from the authors of the paper who are Dave Abrahams, Sean Parent, Dimitri Rakhodon and David Sankel. Oh yeah, David Sankel is at Adobe now. He used to be at Bloomberg. Yeah, so they say, we gain three things at once by going all in on value semantics, which are memory safety by construction, thread safety by construction, like Rust's fearless concurrency, and a simple and powerful programming model with helpful diagnostics.
Starting point is 00:31:25 They continue by explaining the val object model and so on, so if you're interested in val language you can read. But it's definitely a food for thought for a future C++. I like that they are keeping a helpful attitude, so to speak. This is what Val has. Maybe something like that could be used in C++. Instead of saying, C++ is crap. Let's just use Val. I think we are lucky to have people like Sean Parence and all these big names trying to contribute back.
Starting point is 00:32:12 Definitely. Right. This one returns, reconsidering concept in place syntax. If you remember the, how should I call them... Concept Syntax Awards of... Good times! ...of the yesteryear. People didn't want to have terse notation because they wanted more syntax. And now this proposal revives Herb Sutter's concept in place syntax P0475, which allows to use auto with curly braces instead of explicitly stating a name of the concept. So in
Starting point is 00:33:00 lambda for example, a code example in the paper says, lambda parameter could be auto curly brace t as a template parameter curly brace ref ref x. So yeah, who knows, maybe at some point the committee will decide that maybe writing integral auto x is not really necessary, and we could just write an integral like Bjarne proposed from the start. I doubt it. Probably people at this point are tired of the conversation. Or they will look at this proposal and say, oh god, yeah, yeah, whatever, have at it. Right, next one is pattern matching discussion for Kona 2022.
Starting point is 00:33:55 And Kona is this week, so we'll have some feedback soon. But Michael Park produced a great paper that summarizes the current point of discussion for the pattern matching feature. He presents history, and I think the current state is inspect type of expression. There are high-level comparison tables, and this paper proposes a match instead of inspect. So instead of writing inspect x curly braces is one is zero is one and so on, you'd write x match curly braces and pretty much similar. I like it. It saves a couple of keystrokes in there. I like it more than Inspect, to be honest, because Inspect, it looks like a... okay,
Starting point is 00:34:51 it's a statement. It's a... I don't know, Match is... maybe it's because I've dealt with Scala previously, which has Match. I think that Match definitely looks better to me. There are some more before and after code snippets. I think match is also more direct, you know, as it means what it is actually doing. Inspect could be something else, and you need to add the is otherwise you don't understand it. I mean this looks good to me. But on the other hand, Inspect syntax clearly uses is and as for pattern matching, whereas match doesn't. And the current vibe of the committee, I think, to make it work with is and as as part of the language to make it possible to cast with is and does. And so maybe they will be able to combine both and switch to match and is and does.
Starting point is 00:35:55 But anyway, it's really good to see that this discussion is ongoing and hopefully we'll get it in 26. Yeah, hopefully one or the other will get it. Yeah. I don't really care which one, to be honest. No, I mean, there is not any problem. I'm happy with either. Just give me pattern matching.
Starting point is 00:36:16 Right, leave a couple of papers for the next time. There's not many left. Or maybe I'll just say a few words. It seems that contracts are making an appearance again. There are three papers. A proposal to publish a technical specification for contracts, or as I call it, just give us something now because there are papers that could work and I think it goes into a bit of history of what happened to the proposals and mentions proposals by
Starting point is 00:36:57 Gabidos Reis and John Lakers and Pianos Stostrup and others sort of yeah let's just release something. And the other two propose extensions to C++ for contracts, like working draft and amendments to the working draft proposed in the same mailing. This is by a Bloomberg developer. And then we have a response to contracts from Gabriel Dos Reis. The main point seems to be, quote, I suggest that we make each of precondition and postcondition a self-contained expression and side effects free when seen from the outside of each of the cone of evaluation.
Starting point is 00:37:45 So I guess more discussions on contracts, but at least there will be some discussions on contracts, which is good. Better than nothing, I guess. But as for will we get them in 26? Hmm, I wouldn't make any predictions. Me neither. Right, and I will show you something that I thought was really important. Brendan Dolan-Gavitt wrote an article called
Starting point is 00:38:19 Someone's Been Messing With My Subnormals, in which he describes an intrusive nature of the GCC client's compiler switch fFastMath. If it's a bug, it's a mind-blowing one, and we should be very aware of it, especially those who work with older compilers, because it might be getting fixed in the new ones, but compiler migration is usually slow, so basically TLDR. After noticing an annoying warning, I went on an absurd yak shave and discovered that because of a tiny handful of Python packages built with an appealing sounding but dangerous compiler option, more than 2,500 Python packages, some with more than a million downloads per month, could end up causing any
Starting point is 00:39:06 program that uses them to compute incorrect numerical results. The discovery is, quote, it turns out somewhat insanely that when FFastMath is enabled, the compiler will link in a constructor that sets the FTZ and DAZ flags whenever the library is loaded, even on a shared library, which means that any application that loads that library will have its floating-point behavior changed for the whole process. And oFast, which sounds appealingly like a make-my-program-go-fast flag, automatically enables fFastMath, so some projects may unwittingly turn it on without realizing the implications. Even worse, apparently, if you use ofast and then want to disable fFastMath with FNoFastMath.
Starting point is 00:40:05 It doesn't disable it. The author wrote a Python script to check if a library was compiled with FFastMath. So yeah, it's... I think it's pretty crazy. Be very careful with your
Starting point is 00:40:21 math options. There was a discussion about it on LVM project GitHub. Someone raised an issue. It's a new issue. I don't think it's been... Oh, the fix was do not build with the fast math. Really? Cool. Yeah, pretty much, yes. It's well known that fast math actually breaks some assumptions about mathematics, about precision. Yeah, this is a bit over the top, but in general, like subnormals and other things may not be
Starting point is 00:40:52 supported because they take extra time. And actually they're not fast at all. So in many cases, subnormals are just running down to zero. And even the hardware coprocessors actually take much longer to compute with subnormals. You can either go fast or you can get more precise results, but not those,
Starting point is 00:41:13 unfortunately. But you wouldn't expect fast math to be intrusive like this. That's the point. Indeed, this is a bug. This is just crazy. For instance, if you enable FastMask, there's no support for infinity, denormals, all these nones.
Starting point is 00:41:32 They simply are not there. So be warned. Yes. So, yeah, that's a bit of a crazy bug to have. Right. of a crazy bug to have. Right, I'll leave you today with several quotes by DM of Engineering on Twitter. New to tech. This will totally work. Tech veteran. There's no way that works. New to tech. I'm proud that my code worked on the first try. Tech veteran. I'm suspicious because my code worked on the first try. New to tech. This code has been running for
Starting point is 00:42:15 two years. We should rewrite it. Tech veteran. This code has been running for 20 years. I'm starting to feel like maybe we've got the bugs out. And new to tech, I'm a magician. I create things from pure thought. Tech veteran. I'm a plumber. On that happy note, that's it for today. Thank you very much for coming. And I'll talk to you soon. Bye-bye. Thank you. Thank you.

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