C++ Club - 150. Concepts, UB, interview questions, Boost

Episode Date: July 5, 2022

I'm joined by Bjarne Stroustrup, Gianluca Delfino, and other colleagues.Video: https://youtu.be/KWcSk1hsZEUNotes: https://cppclub.uk/meetings/2022/150/New episode numbering!...

Transcript
Discussion (0)
Starting point is 00:00:00 Okay, let me share my screen. Right. Okay, so welcome to the meeting number 150. We'll start with the C++ podcast news. C++ cast is on indefinite hiatus. It's a sad day for C++ podcast listeners. Rob Irving, the creator of CppCast, which was the first podcast for C++ developers, decided to hit pause for an indefinite amount of time. His new job is.NET, which means he's not using C++,
Starting point is 00:01:07 and he can't justify spending time on it anymore, because it's quite time-consuming. And it's completely understandable. Everyone is grateful, Reddit is full of praise. One quote is, Great podcast. I'm a bit sad they're invoking the CppCast destructor. I'll always remember this as my favorite programming podcast. End quote.
Starting point is 00:01:39 CppCast had a good run, with Robin, his co-host, Jason Turner, producing an impressive total of 349 episodes over the years. All high-quality content with many interesting guests. I mentioned CppCast a few times in our meetings, and I still have a long backlog to listen to, so it's likely that I will continue mentioning it for some time. All the best to Rob and Jason in anything that comes next. Godbolt Compiler Explorer is 10 years old, can you believe it? 10 years ago, Matt Godbolt open sourced a web tool he built, Compiler Explorer, which used to be called GCC Explorer. It turned into an indispensable tool for visualizing the work of compilers and code sharing. Most people probably just call it Godbolt now.
Starting point is 00:02:34 I do. You not only can use it on its original website, you can also self-host it in case you have additional security requirements or cannot share proprietary code online. A quote from his article. Ten years ago I got permission to open-source a little tool called GCC Explorer. I developed it over a week or so of spare time at my then employer in Node.js and the rest, as they say, is history. And this is how it looked back then. Much simpler and much less capable than it is now. In his article Matt mentions people who supported him and developed Compiler Explorer together and shared some ideas for the future,
Starting point is 00:03:26 like supporting more CPUs and architectures, user accounts, better support for GPUs, and actual support for mobile devices. Right, speaking of online tools, there is another one called QuickBench. It's a C++ micro benchmarking tool that allows you to compare performance of several code snippets using Google Benchmark. It draws nice charts, as you can see, and can also pass your code onto one of the publicly available C++ compilers, including Godbolt and C++ Insights. And speaking of C++ Insights, it's a tool by Andreas Fertig that shows you an intermediate result of compilation of a snippet of code,
Starting point is 00:04:36 so that you can see what actually happens in the compiler. The result is still C++. It's not underrated. It's always interesting to see what the compiler actually does, but not many people actually use this. Definitely. It's like a glimpse into the soul of the compiler, at least the initial stages. Some of the things you don't want to see, but you better see. Yeah. The code is transformed to illustrate how the compiler sees your code. Right. Next, C++ standard stHive update. The long-awaited proposal, which had
Starting point is 00:05:32 19 revisions by now, was discussed again in the committee telecom. And you will not believe what the next steps are. And the next steps are, come back with revised paper addressing feedback. How many more revisions will it take, I wonder?
Starting point is 00:05:58 It took, I think, 26 for concepts. Oh right, so that's not the longest. No, no, no, that was contracts and then it died. Right, well it's sort of going slowly, so it could beat this record. So this Redditor asks, do C++20 concepts change compile time positively or not? On one hand, a C++ concept adds more stuff to digest for the compiler. On another hand, it imposes constraints, hence reducing Sphene stages. Do you have some feedback about this?
Starting point is 00:06:47 And one of the replies says, Very positively, they nearly eliminate the need for Sphenae. And the code is much cleaner. Instead of weird template parameters, you can have clean requirements listed. Jonathan Wakely replies. He's a GCC developer working at Red Hat. He says that GCC has made a significant progress in concepts compilation efficiency lately. He also notes that concepts can be used for member function selection from the overload set and are better at it than SFINAE. Concepts allow the constraints to be expressed in a simple form that takes less work to compile and that can be optimized internally by the compiler more easily than SFINAE hacks.
Starting point is 00:07:39 Additionally, subsumption and partial ordering of constraints means that you don't need to repeat the constraints on every overload. For example, if the enableIf constraint above in this code snippet if the enableIf was used on one member of an overload set, you'd also need to negate that constraint on the other members, which you don't need for concepts. Yep, very nice and expected and predicted and it's very nice that somebody puts this information out publicly. Well, yes. It simplifies a lot of code. C++20 features are becoming more available to people who are switching to newer compilers.
Starting point is 00:08:36 And so more and more articles of that sort are starting to appear. Tristan Brindle raises this interesting point. Quote, just to add to this, another benefit of concepts is that they can be used in places where Sphenae can't, like on destructors and copy-move constructors. This is useful for things like stdoptional, whose special members should be trivial whenever the equivalent operation on T is trivial. His example code snippet is a partial declaration of optional class template that has two destructors, one defaulted for when the contained type is trivially destructible with a requires clause after the parentheses that uses std is triviallyDestructible and another user-defined one for when the contain type is not
Starting point is 00:09:27 truly destructible, which has a body that calls the contain type destructor. This leads nicely to the next topic. Rainer Grimm posted an article on his blog about using requires outside concepts. I know it's not the ideal usage, more of an ad hoc usage, but still as a way to get more people to use concepts, I guess that's allowed. As you can see here, you can use requires in static assert. This function returns checks that a class has a way to return the count of objects,
Starting point is 00:10:29 and that count is convertible to int. You can also use requires in constexprif. This is a function that can return the number of elements in a container or a custom class, and one of those classes can use a function that differs in name from another one, like count and size. And if you use the requires in if constexpr, you can support both in one function. It seems to be a very good use of requires. I've used this myself and you can use it in const evaluated contexts as well and you know it does save a lot of template instantiations and complications in the code.
Starting point is 00:11:26 It looks very good to me. In many cases, it's a bit of a hack because it doesn't document what you really are doing, it just says how you're doing it. In other words, if you are doing something principle, the likelihood is that it actually should be a concept and have a name. Definitely, yes. You know, just not the requires, but the concept in the if statement. Exactly. I certainly use concepts for that, both in static assert and in constexpr. But I'm leery of code, even if I write it, that uses, requires all over the place, because it's like putting the contents of a function inside something, and you don't really know what's meant. You know what's meant. You know what's done.
Starting point is 00:12:28 Yeah maybe in this case it could be viewed as a as a first step towards extracting these into a concept. Yes that's one way. I've certainly done exactly that. I wrote something, and thought, oh god, this is a hack. This should have a name. I might be able to use it elsewhere. And I mean, a concept is a function, as you see here. Another interesting use case is to put a constraint on a non-type template parameter. Let's see if I can find that example. Oh yeah, if you have a say an int non-type template parameter, you can add a requires clause to limit values to particular range. Rayner also describes the requires requires thing or anonymous concepts. This requires requires,
Starting point is 00:13:41 if you remember, attracted attention and undeserved ridicule of concept skeptics back when they were introduced. I know I remember at least one presentation when this was laughed at. Reiner says, you can define an anonymous concept and directly use it. In general, you should not do it. Anonymous concepts make your code hard to read and you cannot reuse them. So the first requires in this is the requires clause and the second defines a requires expression. And as usual you shouldn't try too hard to make ugly things pretty.
Starting point is 00:14:32 And this stuff is very often ugly. Yeah. So a very interesting article and I hope to get more into concepts as I gain more experience using C++20. Next, we have this article by Mohit Saini. Shocking examples of undefined behavior. They are not that shocking if you already know about UB, but if it's your first encounter, boy are you in for a surprise. The first example of UB by Eric Musser originally is signed into Jira Overflow combined with optimizer.
Starting point is 00:15:22 And there is a Godbolt link for that. Initially it wasn't supposed to be an endless loop, but as you can see here it's not an endless loop when it's compiled without optimizations, but as soon as you try to optimize it it turns into an infinite loop. How does that happen? It's very weird. So the initial code is a loop that loops from 0 to 9. And there is an output statement that outputs a result of multiplication of the loop variable to a very large integer. So what the compiler does in its first step of optimization is a bit
Starting point is 00:16:22 unintuitive, but if you stare at it long enough, it kind of starts making sense. The compiler is... sort of hoists the calculation one level up to the loop condition and increment. And so in the cout statement is just the loop variable. Now the compiler assumes that signed integer overflow never happens in a valid program because it's UB. And so the next step, the compiler reduces that multiplication to true. Because... Didn't the compiler just introduce
Starting point is 00:17:07 UB? Well, the loop would have resulted in UB anyway. I think that's the idea of the original author. So the
Starting point is 00:17:24 J times that large constant is u b and the compiler is allowed to do anything. Yeah. So after that, the compiler thinks, oh, so the right hand of this comparison is larger than int max, which cannot happen. So let's just turn the whole condition to true. And so the loop becomes infinite. Very weird. The second example I've seen before, it was originally shared by Krista Wolfritzen, and it's about dereferencing a null pointer. Let's look at it in detail. Let me try and show you the godbolt for it. So what happens here? The function neverCalled is never called explicitly in this code snippet. Nevertheless, as the result of the compilation, the function eraseAll is called, which is
Starting point is 00:18:41 surprising and potentially disastrous. If this wasn't commented out, you'd probably end up losing your file system, provided you're the sudo user. So let's see what the compiler sees in this. Look at the function do that is defined here. It's static, so that means it can only be modified by this translation unit and nothing else. In this translation unit, the only possible values for do are nullpetter and erasal. Since do gets called in main, it cannot be nullpetter, as it would be ub, and we can't have that in a well-formed program. That means that do can only only initialized with eraseAll.
Starting point is 00:19:47 And as a nice side effect, let's just turn neverCalled into a noop. And so, it happens that main just calls eraseAll. Boom. Ah, compilers. A Redditor suggests a solution for the first case. Well, kind of solution, or mitigation, I'd say. There is a flag that you can use in GCC and Clang, which is fwrapv, and that makes signed integer overflow defined by telling the compiler to assume that signed integers wrap using two-complement arithmetic on overflow. Another editor attempted to suggest using unsigned integers with defined overflow semantics,
Starting point is 00:20:49 to which there was a reply. The problem is, they have very unhelpful behavior a lot of the time, and are widely considered a mistake in the standard library. Glad we got that solved, and we'll never need to revisit it again ever. As ever, there is someone telling us that Rust does it better. And I like a quote in the thread which goes like this. The UB comes first, the unexpected results follow. Library. A Ukrainian developer living in Kyiv, Daniil Goncharov, developed a utility library NameOf for obtaining a string representation of pretty much any C++ object at compile time,
Starting point is 00:21:47 be it a variable, a member variable, a type, or even a macro. It's a single header file with lots of magic, and it can be a great help for logging and debugging. The library comes under MIT license, supports Windows, Linux, and macOS, and can be installed using a VC package or just by incorporating the header in your project. Much of the functionality uses a compiler-specific hack based on the macros pretty-function and func-sig, which work on Clang, msvc, and gcc. There is also discussion on Reddit, and while browsing Daniil's code, consider supporting Ukraine in the fight against Russian invaders.
Starting point is 00:22:45 xMake. 266 has been released. xMake is a very capable cross-platform build utility and package manager based on Lua. Strong pre-make vibes here, but it's much better. It supports other package managers like Conan and VC package out of the box. It also supports modern C++ features like modules. From what I can gather, it supports them better than other build systems. It can generate project files for Visual Studio, CMake, and Xcode. It comes with sensible defaults and is generally very pleasant to use. In this version is support for NVIDIA HPC SDK compilers for C, C++, and Fortran. And support for distributed compilation, which is cross-platform, works with MSVC, Clang,
Starting point is 00:23:50 and GCC, builds Android, iOS, Linux, Windows, and macOS programs, has no dependencies other than the compilation toolchain, supports load balancing and scheduling, supports real-time large file compression transfer using LZ4 algorithm, and has almost zero configuration cost. There's no shared file system required. Sounds pretty cool. Give XMake a go for your next pet project. I did and so far I'm pretty happy. You're not looking back to CMake? Oh no, god no. Not for my pet projects. Life's too short. Right, C++ interview questions. A Redditor asks, what are some C++-related questions that you have been asked in a job interview?
Starting point is 00:24:51 There are various questions of various difficulty levels from beginner to advanced. And I will quote a sampling of replies from the thread. What is polymorphism? Make a polymorphic container. What are smart pointers? Prove you can use them.
Starting point is 00:25:12 Explain virtual tables. How do you allocate memory in C++? How does it differ from C? Well, for a C++ role, I'd say that difference from C is maybe not critically important, but still useful. How do you allocate... oh, sorry. In Java, they got try, catch, and finally. The latter performs some code, no matter whether an exception was thrown or not. We've got no finally in C++. How do we achieve the same effect nonetheless? For this one, array.ai is the best answer.
Starting point is 00:25:50 And you can also use some utilities like GSL finally, I think. Exactly. I mean, it's 10 lines of code. It's still based on arrayII, but if your classes don't support that directly, then you can use that. And you hope that we're going to ever get finally standardized? Sort of.
Starting point is 00:26:20 This is a standards committee, so it becomes much more complicated. It's not just final. It's like finally, but you can say that it's only recalled when it's an exception or only recalls when it isn't an exception. And you can turn it on and off. This is supposedly an improvement. I like the simple finally. I also like the simple final. I also like the simple one.
Starting point is 00:26:47 I don't know what was wrong with it. It doesn't do anything. It doesn't do everything that somebody could imagine. It doesn't do perfection. Right. And of course, it also means that you can see one of those, and you don't really know what's going on. Because in the code, after you've set the final reaction,
Starting point is 00:27:13 somebody might turn it off. Yeah, that's not ideal when you're relying on it. I strongly prefer the simple. Can't do interesting. Yeah. I think Boost also has. It's like my argument against GoTo. It can do everything.
Starting point is 00:27:39 That's why we don't want it. Yeah. I think Boost also has one if you don't have access to GSL, like for an older code. I think GSL requires C++14 now. Microsoft's GSL. Another question, or rather quote I had my last C++ interview
Starting point is 00:28:11 three years ago and the references weren't mentioned at all then again I'm in the game industry which is notoriously resistant to modern C++ I wouldn't say references were more than C++ it's like C++ but yeah game industry I wouldn't say references were more than C++. It's like C++.
Starting point is 00:28:28 But yeah, game industry. 1983? I think in Doom and subsequent engines, the references were banned. I think, I don't know until when, but probably until recently, they were still sticking to pointers only. So it was C with classes
Starting point is 00:28:52 kind of thing. And references were already kind of forbidden luxury. Yeah, there's a whole repository of guidelines called Orthodox C++. It's like anti-modern C++, but it's a very hard reading. Another question. You need to push one million elements to the container using pushback method. Which container
Starting point is 00:29:25 will you choose? StdVector or stdList and why? And the following follow-up question was how many memory allocations will happen if you use pushback in vector to push 1 million elements? And the answer is the number of allocations depends on implementation but will often be log2 of the 1 million elements, because by default most often vector allocates twice the capacity each time it runs out of space. Of course a better solution is preallocate. allocate. Another one, what's the difference between MakeShared and SharedPointerConstructor? That's related to the control block which is allocated in one block and two blocks if you don't use MakeShared.
Starting point is 00:30:20 This is the kind of question that people ask when they just found out about this, and they think, ah, this is something that is a good thing to know, and I want to ask. I know about it. Let's see. My experience is that students coming out of university doesn't know this on average. That's not the kind of stuff they're taught. You can argue that many questions in interviews are just details and they are not essential but just a way to demonstrate the interviewer's proficiency and superiority. Kind of a show off, yes. A bit of a dusty corner here and there that you found out and you remember.
Starting point is 00:31:11 Some other questions were, what's the difference between a struct and a union? What is virtual inheritance? What is a union used for? Rule of five, rule of three, RIII, what do they mean? What's the difference between a reference and a pointer? What does the keyword volatile mean? What are the different types of cast operations? What does the inline keyword do? Explain slicing. Explain how Sphenae works in pre-C++20.
Starting point is 00:31:43 Explain what a cross-thread data race is, and if a class has a destructor, it should probably also have a blank and a blank, and maybe another two blanks. What are they? That's the rule of five, which is one of the more useful questions, I'd say. There were a couple of code snippets in the thread. Let me find them. The first one was, what's wrong with the following class declaration? Oh yeah, this one. This class string. What's wrong with it? And the answer was that since the class member variables are initialized in declaration order, string star will be initialized before length is initialized.
Starting point is 00:32:51 And since length is uninitialized, it contains garbage, and accessing it is ubi. Even if you flip that around, the code is pretty bad anyway. Well, it's like a one-issue demo code. Don't pay attention to anything else. But I guess if the person starts telling you what else is wrong with the code, it's a good sign. My question is, how many compilers catch that one? The out of order initialization, I think, with all the warnings on, probably many. I think GCC and Clang will catch it without any... with the all... W-all? W-all? No, hang on.
Starting point is 00:33:59 I'm not sure. W-extra? Something? Yeah, one of those. They will catch it. But I don't think MSVC will. And if you have ReSharper installed, it will sort of suggest that it's a problem. So this is another code snippet. What will the following program output and why? And the correct answer here I think is A, Fo, because calling virtual functions from a constructor makes them behave like non-virtual functions and is generally not a good idea to avoid confusion. I remember reading a C++ hiring advice some time ago. Ask the candidate a complex template metaprogramming question, and if they answer correctly, don't hire them. Good one.
Starting point is 00:34:59 Redditor asks, is Boost still relevant? Is learning Boost still essential with C++20? And one of the answers that I thought was sensible was like this, actually the first one, quote, I'm not sure learning Boost is the right term, maybe understanding that it exists and take advantage of it if necessary. What I tell my new developers is that if you need a container or algorithm or something that is generic and not specific to our business, is to first check the STL and core C++ libraries,
Starting point is 00:35:38 then boost, and if it is not there, look for another open-source solution. If you can't find something that fits what we need, code it yourself or modify one of the existing implementations if that would make more sense. Boost incubates a lot of code before it goes into the C++ standard, so often has things you can't find in C++20." Some of the Boost libraries that could be still useful and were named in the thread were
Starting point is 00:36:08 Variant2, a variant which always has a value, ASIO, also available as a non-Boost library, BEAST, which is networking and web sockets built on top of Boost, ASIO, MP11 and HANA for metaprogramming, MP11, I think, only if you don't mind long compile times, Describe for reflection, JSON parser,
Starting point is 00:36:40 a multi-precision library, and Regex, which is much faster than std regex. To an extent also the small library to interpret the command line parameters, what's it called? Oh yeah, I think it's like boost command line or something like that, or boost parameters, I don't remember, but yeah, I know what you're talking about. Which is a weird syntax to be on X. Yeah. I think it also has a nice feature where you can define parameters using environment variables, which not all command line interpreter libraries do.
Starting point is 00:37:23 There was another great answer from the thread, quote, there is no single thing from Boost that I have a need for in every project, but I nearly always use something. And that poster listed something they used, which was Boost algorithm for various string-related algorithms like trim, split, etc. But some of these are obsolete with the addition of ranges. Specialized containers like flatMap, staticVector and stableVector. Boost lexical cast, because parsing arbitrary numeric types in C++ is still absurdly difficult. Boost process, Boost format, although from now on they will only be using FMT or STED format, and Boost hash.
Starting point is 00:38:15 They continue. Has Boost gotten a solution to the problem that you get all of Boost if you want anything? I think that's still true. Those libraries that are not header-only and produce libraries, they are separate, so you don't necessarily link to everything you need. But Boost is being imported as one thing. So Boost version. And so the problem is you bring Boost into a project to get something specific, and then you wait a year, and then all kinds of strange features has been used. And you can't see it unless you look very careful
Starting point is 00:39:10 yes yes there is a danger of boost creep oh yes but um yeah i don't know how to fight that. Code reviews, probably. Okay, so next one is, Pure Virtual C++ recordings are available. Cybrand writes, Pure Virtual C++, a free one-day virtual conference for the whole C++ community, run in April, and all sessions are now available to watch online.
Starting point is 00:39:52 The titles sound quite interesting. There were pre-conference sessions on MSVC C++ 2023 update by Stefan T. Lauerwaid. Live session, What's New in C++ 23 by Sybrand. A session by Gabriel Dos Reis, persistent representation of C++ for fun and profit. I'm guessing it's related to modules. No, not really. That's the representation that's a development of the IPR, which is, I think, called IFC when it's a really interesting way of having your program represented as a graph and then walking the word and what is new is you can store this one and bring it back again there was a CVPcon 2021 talk by Gabby about that also. It's being open sourced to use it.
Starting point is 00:41:14 But it's basically the old idea of representing a C++ program as a graph. So it's one of the fastest graphs you can traverse. So the fact that it's used in modules is just a small, one small part of its usefulness, I guess. um the design the original design of modules were based on the ideas of how you could represent and use a program based on ipr the fact that gabby was deeply involved in the ipr has been the main person in the development of it into the bottom portion, and that he was the one that did a lot of the modules is no accident at all. Right. Some of the other sessions were Stay Calm and Stress-Free by using a package manager, an overview of VC package,
Starting point is 00:42:26 targeting macOS from Visual Studio, dependent breakpoints, data breakpoints in Visual Studio Code, hot reload for C++, Clang tidy in Visual Studio Code, productivity in Visual Studio Qt C++ tricks. So yeah, a good set of videos that I'll have to watch at some point. I watched two of the short ones that Clang tied in Visual Studio Code. It was really nice. It's just like 10 minutes. It just tells you how to set it up and a quick demo. Very cool. And I think one of the two ones are about breakpoints and if I recall correctly it was about possibly encoding a breakpoint just writing some sort of attributes which I understand if I understand correctly is a feature that is also being discussed for standardization although somewhat controversial for technical reasons.
Starting point is 00:43:26 You just can say in the code here is a breakpoint and instead of just clicking on the line, you can just write break here and if it's running under the bugger then it's going to break. I think that feature is already available in compilers using compiler-specific functions like debug breakpoint that breaks hard. I know that for sure in MSVC there is some compiler-specific one, but if I recall correctly, there is a limit to how many you can use? Like there is a limit of how many you can put, maybe? I think the limit applies to the data breakpoints because they use specific CPU registers so they can only be like four maximum at the
Starting point is 00:44:15 same time it will make sense yes but breakpoints can be scattered all over the place I think the proposal was to introduce std breakpoint and std isDebuggerPresent two functions, maybe the third one break if under debugger or something like that. So maybe you will get them in 26. I don't know, it's definitely interesting. I don't know if I would use it, but it sounds like something that could be there. I don't know if I would use it, but it sounds like something that could be there. I don't know. I think the main problem is that then you have to admit that a debugger existed. Of course it does, but now you have to say what it is in some sense.
Starting point is 00:44:57 And it's very hard to say. This is a break point for the debugger. The debugger is something that is not part of the standard all right i see so somebody's going to say what does that mean i guess it's a similar problem with standardizing pragma once which suddenly introduces a concept of file system into the standard and and and the fact that once doesn't actually mean once if there's a change in in the in the file system or if something appears in one uncoordinated ways
Starting point is 00:45:43 pragma once is extremely useful unless you do something weak. If you have some links, probably that maybe you have some soft links to your files somewhere else, then maybe Pragma once could get confused or something. There's two or three ways that you can confuse pragma once. And, well, go and get modules to work and have that problem anymore. Yes, please. Yeah. Okay, next, we have another library, which is called Libassert. We've all used assertions with some degree of success and in many cases we want to be able to do that at
Starting point is 00:46:35 runtime as well as during debugging, so in release builds as well. So Jeremy Rifkin wrote a super advanced assertion library. In his own words, it's the most over-engineered and overpowered C++ assertion library. When an assertion fails, not only you get a message, a stack trace, and local variable values, but these are all syntax highlighted. Can you imagine that? This is how a failed assertion looks. I'd say that's pretty advanced. I've never seen anything like it. Can we see the assembly that this thing generates?
Starting point is 00:47:23 Uh, no. It's probably too horrible. Does it spell check the messages while it's added? That would be too much. Supported constructs are debug assertAssert, which is similar to Assert. Simple Assert, which is checked in Debug, but still evaluated and returned in Release. Assume, which checks core assumptions, preconditions, and post-conditions in Debug, and provides hints to the optimize and release. Sort of similar to concepts, maybe?
Starting point is 00:48:06 Contracts? Contracts, sorry. Yes, of course. And verify, which checks the condition in both debug and release. GSL also has similar macros, right? I don't know. Yeah, but they are not great we need something better
Starting point is 00:48:31 so contracts are definitely not going uh in 23 but are they going in 26 i don't know i don't know what they are nobody knows at this point that right, they still seem to be mutating. They haven't been brought to the committee as a whole. My impression is that they serve part of the needs that people have, and not all. One problem I have is they seem to be going towards termination as the only possible way of responding to a runtime detection. And that means that there's a fair amount of code that can't use it so if you imagine using a contract in standard library then could not have it run except in debug because you couldn't take termination take to cases anyway
Starting point is 00:49:47 this will come up and it will come up maybe next year in the year when something comes out of static right so
Starting point is 00:50:04 that was the last thing for today and I'll leave you with this tweet that pokes fun at JavaScript, as you do. JavaScript be like, equals equals, the same, equals equals equals, really the same, four equal signs, really actually the same, five equal signs, really actually the same. Five equal signs, you won't even believe how the same those things are. And the last thing is a quote by Fred Brooks who wrote the mythical Man-Month, who says what one programmer can do in one month, two programmers can do in two months. And on that note, thank you very much, everyone, for coming,
Starting point is 00:50:52 and I'll talk to you next time.

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