Algorithms + Data Structures = Programs - Episode 34: Tuples, Arrays, APL & More

Episode Date: July 16, 2021

In this episode, Conor and Bryce talk about arrays, tuples, APL, C++ concepts/CTAD/structured bindings and so much more.Show NotesDate Recorded: 2021-06-26Date Released: 2021-07-16Tweet of impromptu c...onversation at HOPL IVC++ India AMA with BryceFunctional Geekery (Conor’s favorite podcast)CORECURSIVE #065 From Competitive Programming to APL With Conor HoekstraNew Podcast: ArrayCast!SimCorp (company that uses APL)Companies using APL, J, k or qApril: Array Programming Re-Imagined in Lispbooost::hanaC++ std::tupleC++ std::arraySean Baxter’s CircleSwift Tuple TypeC++ structured bindingsP0931 Structured bindings with polymorphic lambasC++ views::cartesian_productKevlin Henney on TwitterThrust open source algorithm libraryCUB open source algorithm libraryC++ Class template argument deduction (CTAD)P0009 MDSPANC++ conceptsIntro Song InfoMiss You by Sarah Jansen https://soundcloud.com/sarahjansenmusicCreative Commons — Attribution 3.0 Unported — CC BY 3.0Free Download / Stream: http://bit.ly/l-miss-youMusic promoted by Audio Library https://youtu.be/iYYxnasvfx8

Transcript
Discussion (0)
Starting point is 00:00:00 I have a second podcast now. Do you know about this? I don't and I feel betrayed. Welcome to ADSP, the podcast episode 34 recorded on June 26, 2021. My name is Connor and today with my co-host Bryce, we talk about a plethora of topics including std tuple and other tuple types, std array, APL, and so much more. I saw that you were on, like, I saw a tweet where there was a screenshot of you and, like, some other people on some panel at some programming language conference. There's a bunch of things.
Starting point is 00:00:44 You're on panels it wasn't a panel it was an impromptu conversation um uh let's i'm gonna get well so what are all the things to announce because i we do such a bad job of promoting stuff in general um so one I was on I'm doing an ask me anything next Friday July 2nd at I don't remember the time but there's Twitter details I'm doing an ask me anything
Starting point is 00:01:15 for the C++ India meetup yeah Connor will put a link in the show notes so come ask me questions about stuff okay C++ India AMA Um, yeah, Connor will put a link in the show notes. So come ask me questions about stuff. Okay. C plus plus India, AMA. Um, I'm not even sure how much of this stuff you, you know, personally. So, uh, I was on my maybe second favorite podcast, uh, co-recursive, uh, which was,
Starting point is 00:01:39 it was awesome. I talked about the first half was talking about this one. This one obviously is your favorite podcast, right? No. ADSP is your favorite one? No. My own podcast is not my favorite podcast. My favorite podcast is Functional Geekery, which everyone should go listen to. Honestly, at some point I'm probably going to go back and re-listen to all the episodes
Starting point is 00:01:59 because they're so awesome. But yeah, I was on there. I talked about competitive coding and then APL for the second half um lots of great apl content i have a second podcast now do you know about this i i i i don't and i feel betrayed uh yeah so i'm i'm host of another podcast called arrayraycast. Yeah. And it's a panel podcast. Full disclosure, I don't do any of the editing work for this one. That's Bob Terrio, who's one of the panelists. So basically it's four folks and we rotate some of the co-hosts. So like I'm the host that doesn't know anything.
Starting point is 00:02:40 And then we usually have one representative for each of apl uh j which is like an apl derivative and then uh q slash k which are also apl derivatives and we just talk about uh array programming language stuff and i'm we're bringing apl back from the dead even though some people would argue it was never dead um wait which people which people would argue it was never dead uh i mean like that are which people that are not named con the people that work for uh dialogue apl that implements the interpreter that many corporations use so there's also who are these who are these mini corporations so simcorp is probably like the largest uh company that they operate in the financial software section so i'll link it um here let me find it uh because i tweeted it out you know i'm not sure if you're familiar that like
Starting point is 00:03:39 there's a haskell list companies that use Haskell and like companies that use Elixir. Um, there's now a, and they're usually hosted on, um, on GitHub. There's now a companies that use array languages. Here, let me send this to you.
Starting point is 00:03:59 It's a short, what is an, what is an array language? Well, to learn that you should go listen to episodes 1, 2, or 0, 1, 2, and 3. Literally, I think there was an episode that just got released today, which is June 25th, and listeners will be listening to this sometime in July. And we talked about, yeah, what's an array?
Starting point is 00:04:23 What is the array oriented paradigm but it's basically it's a language that basically only has arrays and um yeah this actually is interesting because i i have a the the what is an array in this context does it imply contiguous storage or is it just a sequence um that's actually discussed so like it depends on the language k it's not always contiguous apparently um k and q they treat their like matrices as uh you know a table of vectors so like a a list of vectors where each of the vectors are, I'll bet that's the thing is I think they're vectors. If I recall Nick,
Starting point is 00:05:10 what he said is that they are not necessarily homogeneous. So which necessarily implies that you're either going to have to like box them in order to get them contiguous. But in J and APL, they're definitely contiguous. Yeah, I think in C++, the analogy for what an array language is called array is just the notion of a sequence or perhaps thinking a little bit more modern C++, the notion of a range. So when I say a sequence, I mean a sequence as in like what we call the sequence algorithms
Starting point is 00:05:52 in the standard library algorithms that operate on ranges of iterators. And it's an interesting thing to think about because they're, you know, one-dimensional. You know, they go from front to end. They're homogeneous in that they, at least in C++, they have a single type. could, you know, you could through boxing or type erasure, of course, hold things that have different actual types or kinds in a sequence. And, you know, we have this notion of different categories of sequences, which are sort of come from the categories of iterators. And, you know, the most useful from the perspective of somebody implementing the algorithm,
Starting point is 00:06:59 a sequence algorithm, is, of course, contiguous. Having a guarantee that all the elements of this sequence are that you not only have random access to them, but they're all contiguous in memory. And that's great. If you only have to write an algorithm that works for that, like that's, that's a lot easier. But from from the user perspective, the most useful thing is when an algorithm supports all classes of sequences. And I'd actually be curious whether other languages have the same notions of categories as C++ does. I think things from forward iterator and up probably do map, but do other languages like apl and j do they have a notion of um of input
Starting point is 00:07:50 of something like input iterators where you can only decrement you can only dereference it you know once no at least not to my knowledge like apl isL is a much simpler, has like a much simpler model. Just everything's an array. It has a rank 0, 1, 2, 3, to up to like 15 or something, which just specifies the dimensionality. So like a zero. Why up to 15?
Starting point is 00:08:17 I don't know. Why is it arbitrary? I think it's arbitrary. But why isn't it, why doesn't it just like support like any dimensionality? I do not know um i know that there is an implementation of apl in common lisp uh called april that due to the
Starting point is 00:08:35 fact that lisp supports like infinite dimensions on like nested lists that there's no limit in that sort of apl implementation implementation called April. But yeah, I'm not really sure what the limit in APL is for. And, you know, I think one of the unfortunate tragedies of C++ is when we built heterogeneous sequences, it stood tuple. We did not build it in a way where we could reuse the same series of algorithmic primitives
Starting point is 00:09:19 for both heterogeneous and homogeneous sequences. And I don't know about the rest of y'all, but anytime I end up doing something non-trivial with stood tuples, I end up writing some series of tuple algorithms. And like these just, these just get, some set of these just gets copy and pasted from one project to another project to another project. Like, you know, tuple pushback, tuple
Starting point is 00:09:52 pop, et cetera, tuple reverse, a bunch of, a bunch of like little algorithms like that. And, um, and every time I, I do that, I'm just like, why can't I just call the standard algorithms on these? Yeah. Isn't that what Louis Dion's Boost HANA is for? Yeah. Yeah, exactly. That's exactly what it's for. Yeah.
Starting point is 00:10:15 So why aren't you using that, Bryce? Yeah, that's a good question. A lot of the projects that I work with, it's not, you know, I used to work on HPX where we used Boost for everything. And then since I've started working on other things like, you know, Thrust and Cub that Thrust should stand alone, that it shouldn't really have any dependencies. We'll leave aside the fact that it does actually have some dependencies. But his philosophy was it should be super simple to use, and so we should avoid the C++ dependency management problem by not having any dependencies. And amusingly, this doesn't mean that Thrust doesn't use Boost. It just means that the parts of Boost that Thrust really needed to use, Thrust just copied them into Thrust. So like Thrust complex is a very, very, very bastardized derivative of like some boost complex data type.
Starting point is 00:11:30 And same for like the thrusts iteratorcessor layer is derived from HPX's preprocessor layer, which is derived from Boost's preprocessor layer. So the C++ dependency management solution, just copy it into your project. Control C, control V. Yeah. But I do wonder whether, you know, we made a mistake with not making tuple a language construct. I sort of have two different ways of thinking about this. I have both an argument for why it's good that we made it a library construct and an argument for why it was good that we made it a library construct and an argument for why it's, um, uh, why it was maybe a mistake. Um, I'll start with the argument for,
Starting point is 00:12:30 for why things should be library, um, constructs in C++, which is, um, uh, I don't want to say regularity because that has a specific meaning in, uh, in, in the notion of types. And so if I use it casually here, it won't express what I want. So I think I'll say familiarity. Good C++ features have familiarity, which means that they sort of follow
Starting point is 00:13:04 some core basic set of rules and they don't have a bunch of caveats. So let's take an example of something that does not follow familiarity, which is built-in C arrays in C++. Built-in C arrays cannot be returned from functions. They have this weird property where they can decay to pointers. And they have a bunch of weird conversion rules around that. And they have this really weird syntax
Starting point is 00:13:40 where when you're declaring a C style array, you know, you put these brackets and like the placement of them is like a little bit quirky. And like sometimes you have to put a, you know, a specific size in there. And then sometimes it can just be like defaulted. And all of that is unfamiliar. And by that, I mean, it's not consistent with the basic like rules of C++ structs. Um, now you compare that to something like std array. So std array is a modern C++, um, uh, abstraction for, you know, the same sort of thing as a C style array. And when you spell out the type for a std array, it uses a familiar syntax, template syntax.
Starting point is 00:14:36 It doesn't use this weird special syntax where you have to put brackets in a certain place. And so if you know template syntax, how to instantiate a template, then you'll understand that std array syntax. And likewise, std array doesn't have these weird decay rules where it decays to a pointer. You can get a pointer from it by calling a member function. Member functions, that's something that, like if you understand how you call member function, when, like, you understand how you get a pointer from a std array, there's none of this weird conversion rules to
Starting point is 00:15:15 know. You can return a std array from a function. Like, that's sort of what you'd expect to be able to do with the thing. And I call things that behave like this, I call them struct abstractions. The nice thing about C++, you know, structs or C++ classes is that there's a common set of rules that they follow about what you can do with them. And they have a common and familiar syntax. And so, you know, I think that std array is a much better abstraction than built-in C arrays because std array follows almost like almost all of the same rules as something like std vector or std string, where they're all structs. And so they all play by, you know, a very similar set of rules. And so in that same logic, like, you know, it's nice that std tuple is, you know, just another struct because it follows all the rules of structs.
Starting point is 00:16:14 And the reason that this is nice is because it minimizes the number of things that you have to learn, the number of caveats that you have to learn about the core language. You know, if we never had built-in C arrays, if we just had std array, then you wouldn't have to learn all these caveats of, oh, you can return, you know, you can return any object from a function except for built-in C arrays. Then it would just be, you can return any object from a function. Boom. Done. And likewise you wouldn't have to learn all this weirdness with pointer decay and all the implications it has on overloads.
Starting point is 00:16:53 So I think the best C++ language abstractions for object-like things behave like structs, like as if they were library abstractions. Now, perhaps the mistake we made with std tuple
Starting point is 00:17:14 was that we got the... I would argue that we sort of got some of the basics of the interface right and that we decided to make it a struct-like abstraction. But living within those rules really complicated its interface and I think prevented us from having something that could have been a lot more elegant, like some generalized form of parameter packs. And so like, you look at some of the unwieldiness of dealing with std
Starting point is 00:17:51 tuple, and you wonder, well, okay, you know, is this really worth the cost of having it behave like all other struct like things? You know, like the std git interface in particular is just kind of... The whole time you've been saying all this, I've just been like, you know, like the std get interface in particular is just kind of... The whole time you've been saying all this, I've just been like, you know, whether it's a library or language thing, it's just like having to spell out std colon colon get angle number angle paren, then your tuple type. Yeah. Um, especially when you compare it to like other languages that have tuples, uh, some types and like pattern matching and destructuring, like all built in as sort of language, um, facilities. Yeah.
Starting point is 00:18:34 It just makes you cringe when you have to like, oh, I need the third, third item from this tuple. Let me, let me go. And what did they call it? Cancer of the semicolon, um um or that kind of thing it's just it's very non-elegant um compared to other languages and and if you look in and yeah and you know like it is familiar but that comes with a cost like it does have a familiar syntax for other struct like abstractions but it comes with a cost. And if you look at the design of std get in particular,
Starting point is 00:19:07 there's a reason it's not a member function. And the reason it's not a member function is that if it was a member function, then in dependent contexts, you'd have to write.template get, which would have just been atrocious. I think there's probably other reasons why it's not a member function too,
Starting point is 00:19:25 but I think that was one of the main ones. And yeah, and the syntax that I think we would have wanted, you know, just like a bracket syntax for accessing members of the pack. You know, perhaps we could have found a way to have done that while also having tuple be still a struct-like abstraction. Maybe we could have extended the language in some way to allow an indexing operator that takes a constant parameter.
Starting point is 00:20:13 And maybe that would have been a better design. Or maybe we should have just introduced it as a full built-in language facility. I definitely feel like the way that we went about doing Tuple was probably not right. And this is all leaving aside just the implementation burden of Tuple. Tuple's very difficult to implement. It's very difficult to implement correctly um and uh at times it can have you know big compile time or at times if implemented in like uh uh naively it can have big compile
Starting point is 00:20:56 time costs um and you know i've been looking a lot at uh at sean baxter's Circle recently. And that's really sort of made me question the wisdom of the design of our tuple because the facilities that he has for dealing with tuples and parameter packs in Circle are far more elegant and powerful, and they do actually sort of satisfy my familiarity goal, that they just sort of seem like natural extensions of the language. Yeah, it's interesting, because I looked up Swift's tuple, and for the record, for all those that are cringing because of Bryce's incorrect pronunciation, I do have the correct pronunciation of tuple because Stefan Laowade is the arbiter on this, I believe.
Starting point is 00:21:56 Swift's philosophy is to push as much stuff to the standard library as possible. So like if I'm not mistaken, like their integer types are like library. They're implemented in the library, not in the language. So it's, you know, one of its goals as a language is to basically push as much stuff as possible to be implemented in the library, which then gives like users of the language just as much power as like the
Starting point is 00:22:27 implementers of the language. And that being said, I believe from looking at their docs, their tuple type is a language facility. It's not implemented in a library. So for a language that like has that as a, as a, as a goal or sort of a tenant it. It's interesting because I was expecting actually
Starting point is 00:22:46 Swift's tuple to be in the library and it does not look like it is. I could be mistaken. It does seem like it's something, it does seem like something that's perhaps fundamental enough that it needs to be part of the language. But I would, I think that I still believe that the right answer for most facilities is to implement them as library abstractions because library abstractions have this familiarity.
Starting point is 00:23:15 The place where I think we may have gone wrong is that we did not – we built Tuple as a library abstraction with the tools that we had available and i don't think we spent enough time asking ourselves how could we have how could we make a better like what language facilities would we need to make a better library tuple in c++ and i think that that perhaps with with the right set of tools we could have made a better library tuple but um i mean but you you still you know anything that's in the standard library you're gonna have to pay that um that five character tax stood colon colon and that is a little bit unfortunate well i mean we have structured bindings now so uh yeah that that yeah that does avoid stood get many times we need them everywhere though you i finally remember i i you gotta write me that paper a couple years ago was like oh we need we need structured bindings in lambda uh lambda uh parameter
Starting point is 00:24:28 lists yeah and then you were like huh why is that useful and then fast forward two years and you were like yeah then trying to try to i think it was literally with cartesian product which is one of the it was with cartesian product and i was i was i wanted to make slides and i was like if i don't have this the slide is less elegant and i need this slide to convince to convince the masses the the hbc masses that uh c++ standard parallelism is the way to go so now connor yes i care about your thing bring me bring me that thing technically there was a paper i'll link it in the show notes from a few years ago but it died it was called like generic lambdas and yeah generic lambdas with structure bindings or something like that but yeah but i want you to revive it okay but um but yeah i was just as i was saying that about you know the five character tax i was just thinking you know with um with return
Starting point is 00:25:23 type deduction with automatic return type deduction, with automatic return type deduction and with things like structured bindings, you don't really actually, it doesn't actually really come up that many places. And structured bindings are really interesting because, um, they, I think they change a lot about how we design APIs. Um, an example, one of the things I've spent a lot of time on recently has been shepherding the executor's effort in C++. And in the latest proposal, there's this notion of a thing called a sender that can send values and it can send potentially multiple values. And so that is represented as a tuple.
Starting point is 00:26:11 Usually you don't see the tuple because typically the way that those multiple values get materialized is as multiple function parameters. So usually the thing that, you know, if you're building a chain of asynchronous work, you don't usually see the tuple. It's just that, hey, you have a function that takes, you know, three parameters and the tuple gets, you know, the tuple that's sent gets unpacked and passed in as those three function parameters. But at the end of the chain, when you're waiting for that chain of asynchronous work, then you're getting back the final result. And that is going to materialize the tuple.
Starting point is 00:26:54 And so there's this function sync weight, which you give it a sender, and it returns to you the value that that sender is sent. And it will block until that sender has completed and sent its value. And what does that sink weight return? Well, it has to return a tuple because the sender might send multiple values. And we can actually kind of do that quite elegantly, even in the simple case of a single value being sent. Because in that simple case of a single value being sent, you just write auto, open bracket, you know, a, close bracket, equals, sink weight, whatever, the sender.
Starting point is 00:27:43 Now, imagine a world before structured bindings. In that world before structured bindings, writing that simple case would have required you to instead say auto a equals std get zero of this sink weight expression. And I think that if we didn't have structured bindings, if that simple case had to involve that std get call, I think we probably would have designed that function completely differently. We might have said, you know, we're going to constrain this sink weight function to only accept senders that send a single value so that we can just return that value directly. So we don't have to have this horrible syntax for this simple case. But because of structured bindings, we can write this sort of elegant, you know, code for the simple case. And it extends pretty elegantly for the
Starting point is 00:28:41 more complex cases. And so it's interesting that, oh, structured bindings is just syntax trigger. But I think that that syntax trigger completely changed how we would have designed this API and what we would have thought was an acceptable solution for this API. I don't think it would have been acceptable for this api to have returned a stud tuple um if not for structured bindings yeah there's there's
Starting point is 00:29:10 two phrases that sort of i don't not the word is not irritate but just like completely obfuscates um like the importance of something uh one of them is just like syntax sugar because like lambdas are just syntax sugar, but it completely changes the way that like people use algorithms and how easily it is to reach for an algorithm and customize its behavior. So like saying it's just syntax,
Starting point is 00:29:38 it's just like, okay. Everything's just syntax sugar. Like it's all just syntax sugar for like writing assembly. And the other one that irritates me even more is when someone says it's just semantics. And I'm just like, you realize what you're saying, right? It's just the meanings that we attach to the words and we're communicating. Like it's everything is semantics. Like if we don't. I've never heard somebody say that. Oh, yeah. They say, oh, it's everything is semantics like if we don't i've never heard
Starting point is 00:30:06 somebody say that oh yeah they say oh it's just semantics you know tomato tomato which is actually not semantics that's two different uh pronunciations of the same word um yeah it's like oh well you just had a slightly different interpretation of the word and i meant it this way and it's like well you can't just say it's just semantics. That led to like our complete misunderstanding. I think Kevin Henney has said that. He said that in a talk once is that, yeah, he's like, oh, you know, people say it's just semantics. And it's like, that's literally like the most important thing. If I say one word and you have a different definition in your head, we're going to have a problem.
Starting point is 00:30:54 He's somebody we should have on the show because I bet he's another guest that will have some pretty good come sit around the fire and hear me stories. Yeah, we should definitely. There's no way Kevlin Henning. There's not no way. There's a very low probability that he listens to this podcast. But if you're listening, Kevlin come on come on you know there's another feature which i think is often maligned but is actually proven to be quite great which is a class template argument deduction anybody who's been following me on twitter or following what i've been working on the past
Starting point is 00:31:23 couple months knows that i'm very excited about it, in particular in the context of the MD-SPAN proposal, which I actually joined the committee in 2015 to get something like the MD-SPAN proposal into C++. It's six years later, but I'm getting closer to delivering on that goal. But in the MD-SPAN proposal, there's this support for both static and dynamically sized extents. And, you know, that meant that writing out some simple cases like I want an MD span that represents, you know, a three-dimensional matrix was a bit more verbose than you might like. Because you'd have to spell out this like fairly complex set of template parameters like you'd have to do like md span you know left angle bracket double comma extents dynamic underbar extent comma dynamic underbar extent comma dynamic underbar you know close it was it was really unpleasant and then i realized
Starting point is 00:32:41 like a few months ago hey wait a wait a second, with CTAD, we can make it so that you never really have to spell that out. Like you can, in almost all cases, you can just have those parameters be inferred from the constructor arguments and it'll just make the interface so much cleaner. And yeah, and so I've been working on that. And it just, like, again, it's an example of how this, quote, syntax sugar changed the
Starting point is 00:33:14 design. It was such an improvement that one design change that we had made to the MD-SPAN proposal a few years ago to make it to like optimize for a simple use case, which that design change was we made MD-SPAN a template alias that made the simple use case a little bit easier to spell. And then we had this other thing called basic MD-SPAN, which had a more complicated template interface for spelling out the more complicated use cases. And I sort of realized, hey, with CTAD, we make the simple use case simple enough that we don't need to have like this two separate names for this thing and two separate sets of template parameters. Like we can just get rid of that. And I convinced the rest of Library Evolution on that. And I think that's another
Starting point is 00:34:07 example of, you know, hey, through language innovation, we're able to improve our library design. Because, you know, we care about having simple intuitive syntaxes for things. And when we get new ways to make syntax simple and intuitive, that then changes how we design things. Yeah. This is honestly like what you just said. It's part of my reason, like a part of the reason why I love APL so much is like the elegance of what something looks like,
Starting point is 00:34:43 what your expression that you're building up or your piece of code that you're writing, like it affects like the end result. Like, you know, same thing with auto, you know, like in the past when you had to declare, you know, the iterator on a vector, you know, std colon vector angle type angle, colon colon, you know, iterator. Like type angle, colon, colon, you know,
Starting point is 00:35:05 iterator, like, that's just, that's just like, it's ridiculous. And then being able to replace that, like, with auto, I don't know, it just it completely changes, like the readability, the elegance. And like, and readability is, is an important contributor to like maintainability of code and like, you know, future you or future other person being able to like quickly comprehend what that code is doing. And yeah, like so much of like, you know, if you want to call it syntax sugar or just like, you know, what we're using to express the algorithm or the code, you know, whatever problem you're solving, you know, whatever problem you're solving,
Starting point is 00:35:45 you know, expressiveness is so important. And so these little things that if you can, if you can remove something that was redundant, you know, in Java, I think still, you end up a lot of the times, and this was previously in C++, like you've got the, you have to state the type twice. And now it's like a core guideline in the whatever C++ core guidelines is like always use auto whenever the type's redundant and you're spelling it twice
Starting point is 00:36:13 in the same line. And anyways, there's just this like, you know, there's this purity to APL that like, it's just, all it is is like the primitives and it's so pure. And like whenever there's a reduction you always see a slash and uh like in in c plus plus that's hidden you know you have to recognize that min
Starting point is 00:36:32 element and stood accumulate and find if you know they're all specializations of uh you know they're all reductions but it just you just have to recognize it. And the same thing with like accumulate and partial sum. Those are, those are sibling algorithms. You know, one is the incremental results on the way to getting the final reduction. And that's completely obfuscated by the names of those algorithms. And yeah, there's, there's a lot to be said about, you know, over time, C++ is becoming a much, much like the slideware like that you can write now with CTAD and auto and structure bindings. You can actually get like someone once commented on one of my talks that like my C++ code looks very Pythonic. And I was like, that's not a bad thing. thing like well in in one of the you know i i think i think that ctad and concepts have
Starting point is 00:37:32 are sort of like the next step in the expressivity that we got out of um out of auto because the the downside of auto is there are some cases where maybe solely for readability or documentation not because it's like significant but like you just like you want it to be clear in the code that this is that this thing is an integral or this thing is a vector you know that this locally declared variable you know is an integral or a thing is a vector. You know, this locally declared variable, you know, is an integral or a vector, not necessarily something that's a parameter. But like to me, that's really the value of auto. Like I don't, I do use, I guess I'm not a strict adher, like almost always auto. I'll use auto where it like increases readability. But I really love using CTAD because it lets me get a lot of the benefits of auto while also still making it clear what, making it clear what kind of thing this object is in a line, like in some particular like local declaration, like that can be really, that can be really useful.
Starting point is 00:38:55 Just like solely as documentation. I mean, there are cases, you know, where I really, you know, I really don't care what it is, where sure, I can just write auto and that's fine. But this gives you more options without having to be completely verbose. That's the advantage of CTAD. And I think one of the advantages of concepts is that I can avoid verbosely spelling out the entire type of a thing, but also still, you know, describe some of the properties of this declaration. Yeah. I have yet to use concepts like as a, uh, qualifier on a variable type, if that's what you're talking about. Yeah. I mean, it's, it's, it's, I, I find myself using them a lot when I'm in pseudocode, when I'm communicating with others. I am not in a place where I can use them in work code quite yet.
Starting point is 00:39:56 I mean, there are some places where I can. But certainly, whenever I'm just workshopping code with somebody, I'll just default to using concepts. And interestingly, I also will default to using the abbreviated template syntax where you can declare a template function just by using like auto in one of the parameters. And I was one of the people that was a skeptic
Starting point is 00:40:28 about abbreviated template syntax because I was a little bit concerned about the implications of being able to write template functions that were not obviously template functions. But I'm sort of a full convert. Bjarne was completely right about that. And yeah, and I want, I mean, I think that the compromise solution that we have, we're
Starting point is 00:40:52 sort of the auto has to appear in the parameter list. It's not like you can just have the concept name. You have to have the concept name then followed by auto. I think that was a good compromise because it still gives you an easy way to identify that something's a template but uh i think even if we'd gone the other route of just you know solely concept name makes it a template i think that probably would have been fine just just based on how you use useful i've found it to be and how natural it is yeah it's still i feel like people would have up, because how do you tell if something's
Starting point is 00:41:28 an explicit type or a concept if there's no way? I feel like many code bases would end up like, you know. We could have done that by convention. Exactly, yeah. But the committee made what I still believe is a big mistake in that we decided to give standard library concepts snake case names instead of the camel case names that we had been using informally in the community for a long time and that we'd been using in the standard spec to denote name sets of type requirements pre-concepts. And I think that we should have used,
Starting point is 00:42:05 like I think if we had in the standard library used camel case names to the concept names, it would have established that as being the precedent for other standard library-like things. Code bases that use camel case for, and not snake case for like all of their other things, they wouldn't have had a good solution here. i i rolled some os violin for those code bases sorry i shouldn't get all cub yeah yeah one of your two libraries not but that's not by my choice um uh but uh
Starting point is 00:42:40 i i shouldn't uh i shouldn't pretend that i don't have sympathy for a variety of coding styles. I'm just being cute there. I, of course, care about all coding styles. My point is that we could have potentially done this by convention. But I do think that the best convention is the one that we have, which is where the convention is part of the language itself, that there has to be that auto keyword following it. I think that was a really great, a great compromise. Thanks for listening. We hope you enjoyed and have a great day.

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