5

So do we like Generics or not?

 1 year ago
source link: https://changelog.com/gotime/286
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.
neoserver,ios ssh client

Transcript

šŸ“ Edit Transcript

Changelog

Click here to listen along while you enjoy the transcript. šŸŽ§

Hello there, welcome to Go Time. Iā€™m Mat Ryer, and I have a cold. Sorry about thatā€¦ Donā€™t worry, weā€™ve got good editors, you probably wonā€™t notice anything. But I just wanted to let you know Iā€™m not a hero, Iā€™m just doing my bit for the Go community. So please feel free to celebrate that on Twitter.

Today, weā€™re talking about generics. Weā€™re asking ā€œSo do we like generics or not?ā€ Some people feared that theyā€™d be the end of the languageā€¦ You know, that people would abuse it, and use them in all the wrong places. Others were a bit more hopeful. They had clear use cases, and were kind of thrilled that weā€™re getting this feature. But it was also often touted as the reason a lot of people didnā€™t adopt Go. So we have it now; we have generics, our flavor of generics. What do we think of it? Joining me to discuss this - itā€™s my co-host, Kris Brandow. Hello, Kris.

Hello, Mat. How are you doing?

Iā€™m not too bad. Iā€™ve got a bit of a cold, but getting through it. Iā€™m just [unintelligible 00:01:43.08] really just been brilliant. How about you?

Doing great. Itā€™s a beautiful morning.

Good. Yes. And I appreciate this is quite early for you. Weā€™re doing this at a different timeā€¦ So thanks for getting up so early.

Weā€™re also joined by Roger Peppe. Roger has been a Go enthusiast since the day it was released, and has been contributing loads of things to the standard library and the ecosystem. Currently working on implementing modules in the CUE language, cuelang.org. Welcome back, Roger.

Hi! Howā€™s it going?

Good. Not bad. Pleasure to have you back, of course. I like your hoodie. For those that donā€™t know, heā€™s wearing a CUE hoodie.

Itā€™s my favorite hoodie.

Yeah. Weā€™re also joined by Bryan Boreham. Bryanā€™s a distinguished engineer at Grafana Labs, working on highly scalable storage for metrics, logs and traces. Bryanā€™s used Go since 2014, so again, a long time there, and contributes to many open source projects, including - you may have heard of Prometheus, perhaps youā€™ve used gRPC, and I know a lot of you have used Go itself. Welcome, Bryan. Welcome back.

Hi. Thanks for having me.

Pleasure. Cool. So Iā€™m very excited about this episode, because I was one of those people that was ā€“ Iā€™d used generics in previous languages, and I kind of was excited that we were getting it. How do we feel like ā€“ maybe we could just give someone a quick overview of what generics are and when they came to go, just so everyoneā€™s caught up. Any volunteers?

[laughs] Okay. Yeah, I mean, generics - they basically mean you can pass types to functions and methods, and you can have types that are themselves associated with types. Itā€™s all at compile time. In a sense, you donā€™t need generics, but it means that you can have these things which ā€“ where before you might pass a dynamic interface value, and maybe do a type coercionā€¦ The classic case, of course, is with containers. So Iā€™ve made this nice, advanced data structure that holds all my values, and I put a value in, and I know that Iā€™m only going to put integers in there, and I get this thing out, and - oh, itā€™s not an integer anymore. Itā€™s the empty interface. So I have to assert that itā€™s an interface, that itā€™s an int, but maybe I didnā€™t actually put it into there, and so my program panics at runtime.

Also, there are a bunch of performance improvements associated with that, because in that particular example, putting an integer in an interface - if itā€™s greater than 256 or something like that, then itā€™s actually going to have an allocation to put that in an interface. So youā€™re actually paying the price of storing that data, where in fact you just actually only need one little integer-sized slot for it, and that can really [unintelligible 00:04:26.02] Particularly when you have larger data structures which incorporate types. The safety and the performance aspects, both can add up a lot in larger systems, I think.

I think I might want to note that we had some generic types before, since the beginning pretty much; like a map, for instance. Whenever you used a map, you had to put in square brackets what the key type was, and then right after that what the value type was. So map string of string, map int o string, or whateverā€¦ And so what changed - was it Go 1.18? What changed is the kind of availability of the programmer to define their own things, their own types and functionsā€¦. Which still had those little square brackets bit with a type in the middle. So the power was kind of reserved to the Go compiler beforehand, and now we have the power.

Yeah. And have we been wielding that power responsibly?

Well, I was a C++ programmer for a long time, 20 yearsā€¦ And actually, from the time before C++ had generics.

And I think a lot of people feared that Go would suffer the way C++ did, because people started writing programs that frankly no one could understand, using templates, which is the same thing, basically, in C++. I feel Go has largely escaped that. I personally have not really come across people overusing generics.

[00:06:02.16] I think itā€™s kind of too early to say, honestly. Weā€™re just past the point where people are generally using it, where people [unintelligible 00:06:08.20] And I think ā€“ give it a couple of years, two or three years and weā€™ll see, I think, whether things are moving in a dubious direction or not.

Yeah. What do you think about the choice of square brackets? Somebody that was quite new to the language was kind of surprised that it was just using square brackets and not something different, because it was such a different concept. Bryan, you make a good point about maps and slices being kind of the mapsā€¦

Well, yeah, slices, the type, was outside the square brackets. Itā€™s not a great pattern.

And maps too, right?

Well, yeah, maps - you have one type inside the square brackets and one outside. I donā€™t know if we could read too much into that. C++ itā€™s angle brackets; itā€™s less than/greater than, so I guess they wanted to distinguish themselves from that.

Well, angle brackets are problematic, right? Deeply problematic, because youā€™re syntactically ambiguous, because you canā€™t tellā€¦ If youā€™ve got a<b, then you canā€™t tell ā€œIs that the start of a type parameter, or is it not?ā€ And I think thereā€™s lots of good reasons not to use angle brackets for that reason.

I think thatā€™s the same reason we didnā€™t use parentheses as well, because there was some syntactic ambiguityā€¦

Actually, the first generics proposal in Go - well, the first serious generics proposal in Go did use parentheses. So you really can use parentheses, but I think in that case they were considered not sufficiently distinguished. The square brackets - itā€™s somewhat distinguished, but notā€¦ Yeah, thereā€™s still some ambiguity there.

Right. So I guess that would be semantic ambiguity on the human side of like ā€œWhat is this thing saying?ā€ if you use regular parentheses instead of brackets.

Yeah, I think that would look quite weird. Iā€™m just trying to imagine what it would look like with parenthesesā€¦

Yeah, indeed, there were just loads of parentheses. Are we Lispā€¦? [laughter]

Yeahā€¦ Take me back to the ā€™50s.

So have you used generics yourself? Roger, you mentioned that youā€™re currently working on implementing modules in the CUE language. Does that work call for the use of generics much?

Um, no. So I do use generics, and I quite often use them in a local way, that isnā€™t part of the APIā€¦ There was a nice example I came across recently, where I had an interface type and an implementation that basically joined two of those together. And you want to do that in parallel. So for every method call ā€“ and there were maybe 10, 12, 15 method callā€¦ You wanted to make a parallel call to both the underlying values, and gather the results together. And without generics, you would have written a load of boilerplate code. With generics, I could write a little wrapper, and the code was really super-clean, and you could just do it in a couple of lines. Same thing for every function, regardless of the signature in the function. That worked out really nicely, actually. And not only that, you could ā€œOh, well, okay, weā€™ve got the boilerplateā€¦ Well, maybe we donā€™t want to make that. Maybe we want it to be sequential and configurable.ā€ Super-easy.

Right. So how would you have solved that problem if you hadnā€™t had generics?

I would have probably just written out all the code.

Just by hand?

Probably. Yeah. Maybe code generation, but it wouldnā€™t have been too bad. Or maybe some dynamic type coercion. That also. But I would have had to implement a bunch of helper types probably.

Yeah. So thatā€™s it. And I think there are those use cases where itā€™s just perfect. And thatā€™s why I think that I was quite pleased that they came to the language. Weā€™ll talk a bit more about changes in Go 1.21, but I do really like the slices package.

[00:10:02.29] So for anyone that doesnā€™t know, this is just ā€“ you know, thereā€™s common things you do a lot with slices, and of course, Iā€™ve had the case where I wanted to search through a slice, and find something based on some function, something like thisā€¦ And I had to just write that manually for the particular type that I was supporting. I tried doing things with interfaces and things before, but you end up adding a lot of complexity in order to just solve that problem. So I feel like the slices package is going to help us there. Are there any other good use cases weā€™ve seen?

I mean, I feel on the slices package this thing, tooā€¦ I wonā€™t have to google the slice tricks document as much, because thereā€™s some things that it covers, which Iā€™m very happy aboutā€¦ Because it was always annoying finding that thing, even though it was pretty easy to find. I was like ā€œOkay, Iā€™ve gotta google this thing.ā€ Itā€™s nothing like Dash, or anythingā€¦

Yeah. But also, the slice, you almost ā€“ when youā€™re reading the code, itā€™s not always obvious whatā€™s happening.

So itā€™s almost like you need to look at the slices thing when youā€™re reading the code as well. Whereas if itā€™s just ā€“ I donā€™t know, one of the examples, itā€™s much easier to read, isnā€™t it?

So I was ā€“ still in the slices package, I was really pleased that the sorting function there was faster. I always want to make programs faster. And we should say ā€“ so slices will become part of the standard library in Go 1.21, but itā€™s available right now as part of the experimental directory from Google. And I have been using it for like a year. So that change went into Prometheus using ā€“ so where you would previously use sort.slice, you can change that to slices.sort.

Thatā€™s much better, isnā€™t it? Much more of an improvement now. Iā€™d much prefer that.

It is. You can easily see whatā€™s going on. No, really, you donā€™t see it unless you look at a profile. The sort one works in terms of interfaces. So every single time it needs to compare two elements or to move things around or whatever, itā€™s going through dynamic dispatch, through the interface mechanism. So itā€™s doing extra lookups, like ā€œOh, what is this thing?ā€ And in particular, when youā€™re sorting integers, which happens a couple of times in Prometheus, for instance, the generic one just compiles all the way down to the machine instructions for less than. So thereā€™s no dynamic lookup, no function call overhead, no nothing, and itā€™s way, way faster. In narrow, niche case, but it was night and day.

Thatā€™s pretty cool. So does that actually happen when youā€™re passing a function that does the comparison of two integers? So it kind of devirtualizes the whole thing?

Yeah, so thereā€™s two variants. Slices.sort works for things like ints and strings that you can compare with less than. And then thereā€™s a variant which is called slices.sortfunc, where you supply a less function. And that oneā€™s pretty good as well. I mean, itā€™s not as much faster, but as you just said, itā€™s calling through a reference to a function, which is much faster than doing dynamic dispatch on the elements of the slice.

Yeah, I mean, one of the things that I was interested in - itā€™s kind of a bit of a conflict for performance optimization, because in many languagesā€¦ Well, in C++ particularly, but also languages like Rust, when you have a generic type, itā€™s all devirtualized, itā€™s all in-lined, so everything is basically expanded out. So one thing I worry about in Go in the future is that people make something generic because of that performanceā€¦ When actually it would be kind of like a nicer, easier to understand and simpler to use if it was using interfaces. Because the moment youā€™re using generics, you have to pass around that type parameter, although the actual type isnā€™t hidden under the hood, as it wereā€¦ And things become, I think, quite often harder to use.

[00:14:05.17] So thereā€™s a kind of tension there, because if people make generics truly efficient like they can be, then you have this pressure to use generic types, and then you start going down the route of ā€œOh, things become harder to useā€, and Go maybe starts to get that reputation. So Iā€™m interested in what you think about that, Bryan, actually.

Yeah, itā€™s definitely complicated right nowā€¦ And thereā€™s basically two cases. The case where you have some kind of method in your generic. Basically, if your generic type parameter has an interface, which has some methods on it, thatā€™s one case. And then the case where it doesnā€™t have any methods, but you do want to use things like less than and greater than, and it basically has to be one of the underlying types that the compiler handles.

So right now, the first case - it basically boils down to an interface, and itā€™s slightly worse than an interface, because the compiler is passing a little bit of extra information for the generic mechanism. So generic functions with parameters, which are interface type, are not that fast. A little bit slower than interfaces pre-generic. Whereas generic functions taking things which donā€™t have methods can be blindingly fast. Certainly donā€™t have any dynamic dispatch might enable you to in-line things you couldnā€™t do beforeā€¦ So I think thatā€™s already too complicated for your typical Go programmer to really grasp. Thatā€™s really down in the weedsā€¦ Sorry, I donā€™t want to insult anyone; I just mean thereā€™s too much to grok, to get your head around, to read through the details of how this is implemented. And thatā€™s just where we are today, where itā€™s what they call monomorphization. Everything is kind of coerced to look like an interface.

I think in the future, if they do start stamping out multiple copies of the code for different types for performance reasons, then itā€™ll get much harder to understand the trade-offs. I certainly worry a little bit about that. I guess where we are, thereā€™s an uncomfortable thing that happens where you get advice to pass around a function parameter, and thatā€™s exactly why slices.sortfunc has this extra parameter that we kind of donā€™t want to exist. And itā€™s a value parameter, not a type parameter. In C++, that would be a type parameter. That would be parameterization on the type of the function, rather than a value that you pass into the function.

So yeah, weā€™ve got something thatā€™s a little bit ugly, I would say. I guess most people are just perfectly happy to get the expressive power. We should be trying to express programs nicely, elegantly; that should be our first concern. And then make it work, make it run, make it fast. Normally, the last thing you do is performance.

Yeah, my ideal scenario would be where you could use either approach. So you could pass an interface in or you could pass a function parameter in, and the compiler is clever enough to know thatā€™s static, to know that youā€™re always passing the same function, and do the same thing regardless of whether youā€™re using generics or not. And I think it does devirtualization in a bunch of cases. Apparently, profile-guided optimization is clever enough to do that sort of thing now in certain cases, which is interestingā€¦ So you know, thatā€™s pretty cool.

Yeah, but I like that message, this thing of ā€œFocus on making the code easy to read, easy to maintain.ā€ There are times when ā€“ and if youā€™re lucky, youā€™ll reach the point where performance really matters, where youā€™ve got either massive scale, or just youā€™ve got things that are being usedā€¦ It depends on the problem, really. And then itā€™s worth that kind of digging into the details, and maybe even worth a bit of complexity and a little bit of sort of ugliness just for that purpose. And then youā€™re making a trade-off for quite a good reason. But I guess, Bryan, youā€™d recommend you profile first, you gather data, you wait until you have one of those situations.

[00:18:09.04] Yeah. I mean, youā€™ll almost always find that your performance problems are in a few small places. So maybe itā€™s okay to make something that was five lines of code into 30 lines, because thatā€™s the bulk of your performance problem. But donā€™t do that all over the place.

Yeah. And that is tempting. I remember, I just wanted to just have the fastest possible thing. It was almost like I gamified it for myself, of just like ā€œDo I want the best performance? Of course I do.ā€ And I would sometimes trade off the ā€“ you know, I felt like Iā€™m being clever here. Iā€™m doing thisā€¦ And yeah, it might be complicated; you have to be smart to understand it. I wouldnā€™t go as far as insulting half the community like you did, Bryanā€¦

Yeah. And then maintaining that code over time. And where I would forget, Iā€™d be like ā€œWhat on earth is this?ā€ And then I was like ā€œDo you know what? Iā€™ll just rather it was dead simple. Thanks.ā€

Yeah. Well, someone like Brian Kernighan said ā€œYou need to be smarter to debug a piece of code than you do to write it.ā€ And therefore, if you write the code to the limit of your ability, then youā€™re actually not able to debug it.

I love that. That slices.sort - does it work with anything? Can you pass any type into that function?

Only ones that support less than. So ints and floats and strings. But thereā€™s a sort func where you supply a function that implements less, if you have a more interesting type.

Yeah. So this is where constraints comes in. Sort of part of our generics is we have these quite interesting-looking ways of expressing, like, ā€œThis is a constraint of the types that you can pass into this thing.ā€ And there are a few built-in ones, arenā€™t there?

No, in fact theyā€™ve gone the other way. In 1.21 thereā€™s a new package called [unintelligible 00:19:55.22] and I think the main purpose of that is to define an ordered type, which is these things that support less than. So itā€™s in the library, itā€™s not in the language.

I think thereā€™s a differenceā€¦ So thereā€™s two kinds of ā€“ you can constrain something in various ways. It looks like an interface type; a constraint is actually an interface type. And it can have methods like any interface type. So that means that youā€™re constrained, that that type is constrained to have those methods. But also, you can name a number of other types and say ā€œThis interface must be one of theseā€, and you just say [unintelligible 00:20:29.15] or stringā€¦ And that basically means that that value must be any one of those, and if some operation is supported by all of those, then youā€™re able to use it in your generic function.

For example, that sort function can work with less than, because itā€™s got a constraint that mentions all the possible underlying types in the language, of which there arenā€™t that many; like 10, or 15, or somethingā€¦ All the uint types, all the int types, a few others. And because weā€™ve mentioned all of those, it means we can use less than, and we can pass any of our existing types that we can compare less thanā€¦ Which is - you know, thatā€™s pretty cool.

I gave a talk at GopherCon UK last year, where I talked about using unconstrained types, and how they were kind of strictly more powerful. I didnā€™t talk about performance at all there. And yes, theyā€™re definitely less powerful. But the sort vs sortfunc example is an interesting example of that, because you can write one in terms of the other. So you can write sort in terms of sortfunc, but you canā€™t do it the other way aroundā€¦ Which is kind of interesting to me, particularly as sort is more performant as wellā€¦ Which is a bit of a shame, because weā€™d like to be able to write the more generic, the more powerful version, rather than the other one, ideally, I think.

[00:21:59.08] But that actually made me think of ā€“ so thereā€™s one thing we havenā€™t talked about here, which I think just kind of fell out from the design, and I think itā€™s amazingly powerful and quite interestingā€¦ Itā€™s that of generic interface types, which people donā€™t ā€“ Iā€™m not sure people are aware of quite how useful and powerful they are. So you can have an interface type that actually itself has a type parameter. For example, you could imagine a sorter, a comparer interface type that has a method that takes two parameters, both of type t, for any type, and returns boo. So thatā€™s kind of equivalent to a function that takes two [unintelligible 00:22:35.20] but you can have multiple methods.

Itā€™s actually a really powerful paradigm. Essentially, you can define a kind of algebra between your methods in terms of this abstract type, in terms of this type we havenā€™t defined yet, which is quite cool. And because itā€™s an interface, youā€™ve actually got an underlying value. Youā€™re passing this thing of type t into this interface, but youā€™ve actually got a value under there, too. So for example, it could know how to sort. And Iā€™ve used that a few times, and Iā€™ve found it quite interesting. But the performance implications of it - I have no idea. Bryan, you might know - is it efficient to call a method on a generic interface, or itā€™s about the same as calling it on a normal interface?

Methods are slightly worse with generics than they were before methods on interfacesā€¦ So itā€™s a little bit disappointing. So I guess an example which is a little bit like what youā€™re talking about is the heap; not the heap that you allocate memory on, but the one which sort of keeps the smallest element at the front. So thatā€™s expressed in the Go standard library as an interface that has a less method, but also has a swap method and a pop, or a push; I forget exactly what it has. Anyway, I noticed that there wasnā€™t one of those in the slices package, and around about Christmas time I was off work, and I thought, ā€œOh, I should be able to fix that in a couple of hoursā€¦ā€ And this ballooned into something that took weeks, because itā€™s just not that nice to try and express a thing which is a container, and has operations on the objects being contained in terms of Go generics.

Iā€™ve got a talk at GopherCon in San Diego coming up, where I sort of explain where all this landed, which is with a completely different data structure called a loser tree. So I wonā€™t go into the whole explanation of that right now, but anywaysā€¦ The short version is that it leaves a lot to be desired right now, trying to express a kind of a generic thing which operates as a container on other things.

Interesting. So do you think thatā€™s a fundamental limitation of the current generics design, or something that could be addressed with a language change? Or maybe itā€™s just because itā€™s performant [unintelligible 00:24:51.10]

No. Well, itā€™s a little bit of everything. I mean, kind of borrowing from something we thought we were going to talk about later, thereā€™s a function couple of functions, max and min, that have been put into Go 1.21, and I think they form a sort of similar example. So you can write a generic ā€“ in Go you can write a function using generics, which takes a type t, and just basically says ā€œIf a less than b, then the minimum is a. Otherwise itā€™s b.ā€ You can write that, but itā€™s not the function that you want in the case of floating point numbers. Because in the case of floating point numbers they have this exception which is a nan, not a number; and nanā€™s are never less than or greater than. And this is a sort of annoying anomaly. And where that story ended in 1.21, is these things became built-ins in the language. So they sort of cheated. The Kobayashi Maru for feature development.

And itā€™s ironic, because max and min were one of Ian Lance Taylorā€™s kind of red lines. Like, if we canā€™t express max and min with generics, then the generics design isnā€™t good enough, right? But now, ā€œOh, dang it! We still canā€™t express max and min with generics, and weā€™re putting them in the language.ā€

[00:26:08.07] Yeah. So harping back to C++ā€¦ In that language you can write what are called partial template specializations. You can basically say, ā€œWell, if itā€™s a float (you say this to the compiler), I want you to use this version of the code. And then if I donā€™t say anything, just use this other version.ā€ And that technique, that language feature would, I think, get us out of this problem. So basically, I do think thatā€™s the thing that would help - the ability to put special cases into my generics, and say, ā€œIf itā€™s this kind of a thing, then I want you to use this kind of code. And if itā€™s this other kind of thing, then do it totally differently.ā€

So this is a proposal that I made a little while ago for type switching on generic types. Itā€™s issue #45380.

Oh, how could I forget?

But would that give you what you want?

I have to confess, I havenā€™t read it. I mean, maybe. Basically, what you donā€™t want is for the runtime to be executing these types. You donā€™t want to be executing these types at checks at runtime, which is kind of where you might try and do it today. It would work, but it would just be horrible in performance for anything low-level, like a sort, or something like that. Yeah, so if the compiler is doing it at compile time, that would be better. I mean, is it literally a switch, like with key statements? Is that what you proposed?

Yeah, pretty muchā€¦ Except the target of the switch is the type itself, rather than a value.

Yeah, itā€™d be interesting to try it out. I mean, all the other things that Iā€™m familiar with in that space tend to do more of a pattern-matching approach. I guess Rust does that, doesnā€™t it? Iā€™m not a big Rust user, but I think it borrowed the idea from Haskell, which sort of borrowed it from ML, which I did learnā€¦ Yeah, so I think conceptually itā€™s a little bit nicer to sort of write out the patterns of things that youā€™re trying to match, and the code that goes with those.

I mean, this wouldnā€™t allow you to do something like ā€œOh, slice of anythingā€, right? Youā€™d have to type switch on specific types. Because otherwise, I think it might be ā€“ otherwise, basically, youā€™re in inflection territoryā€¦ Not great for performance.

Yeahā€¦ Interesting future anywayā€¦

Yeah, well, that definitely seems doable. I was just scanning that proposal, Roger, and I feel like that could be done at compile time, right? I meanā€¦

Yeah, it could definitely be done at compile time, yes. One of the things about generics is fundamentally, itā€™s all exposed ā€“ logically, itā€™s all expanded out at compile time, even though it might not actually be fully expanded out at compile time. You have all the information you need. You canā€™t dynamically generate dynamic generic types. Although, theoretically you can, except the compiler finds it out and says ā€œNo, no, you canā€™t do that.ā€ Because you can have a recursive type, you could have a recursive type that has a type definition in there, which involves two of the original, and then calls itself, and then you get this blob of an infinite number of generic types, and the compilerā€™s like ā€œNo, noā€¦ Not today.ā€

How would people show support for that proposal? How does it work? Like, I noticed that thereā€™s thumbs up, and thingsā€¦ Do people pay attention to that?

I believe so. I mean, no oneā€™s come out ā€“ I havenā€™t seen any anyone come up with a good [unintelligible 00:29:31.29] I think they just need to have the energyā€¦ The Go team need to sort of say ā€œYeah, this is worth working on now.ā€ Because I think last I heard, Rust was like ā€œYeah, for later.ā€ Itā€™s a proposal hold, is what it is. Too much for now. And you can kind of do it at the moment with a dynamic type switch.

Iā€™m surprised you yourself havenā€™t been put on proposal hold, Roger.

I am pretty much on hold [unintelligible 00:29:58.02] I would sayā€¦

Yeah. Because Roger ā€“ yeah, arenā€™t you responsible for the error interface?

[00:30:05.24] I did, I did suggest the error interface, and they saw it and said ā€œAh, yes, this is what weā€™re looking for.ā€ Because they were about to propose the error thing ā€“ that it just be a package that you imported everywhere. Everywhere weā€™d have to import errors, and say [unintelligible 00:30:17.19]

Well, then itā€™s more popular than Testify at least, until thenā€¦ Oh, by the way, Iā€™ve found out at GopherCon ā€“ we did a panel with the Go team. Iā€™ve found out that Testify, my package, is banned in Google.

So thatā€™s going on my resume. What do you mean good, Bryan? Donā€™t you use it?

Well, I think conflict is good for ā€“ a bit of tension, a bit of dramaā€¦

Well, I could use that as a moment to shout out at qt, which is my generics-based testing package, which I quite like. It kind of has fake heritage from Gustavoā€™s Check package, originally. But anyway, yes, it uses generics, and I quite like it, because itā€™s small, which I donā€™t think you can accuse Testify that it is small.

No. I also had that same feeling, and I actually have another package, which is on GitHub, matryer/is. And that is ā€“ I call it ā€œTestify off steroids.ā€ Itā€™s like the minimalist version, for the same kind of reason. But itā€™s not generic, so thatā€™s quite interesting. I wonder how.

Yeah, so this is quite nice, because if you want to compare two things - you know, for equality, or particularly for not equality, you want to make sure that theyā€™re actually the same type. And generics can do that quite nicely. And I quite like ā€“ the other nice thing, I think that that is composable. So you can put these things together and you can make new checkers, which all fit into the same framework. Iā€™ve been using it recently and Iā€™ve been quite a bit quite happy with it. I shall post a link to it.

Yeah, weā€™ll put a link into the show notes for that. Very cool. I was gonna ask ā€“ oh, itā€™s literally qt, the letters?

It [unintelligible 00:32:08.16] fairly small prefix.

Good thing we have a link, because I think people googling qt are going to find not thatā€¦

This is true. This is true. Actually, I should shout out Francesco Banconi, who wrote the original Quick Test. He was a previous colleague of mine, so we wrote it together, basically.

Nice. So when it comes to like people choosing to pick up generics or not, is this sort of advice ā€“ like, we sometimes say ā€œIf youā€™re going to do an abstraction, solve the problem a couple of times before, and that really helps figure out what the right kind of abstraction isā€, or if indeed there is one thatā€™s suitable. Do we have the same kind of advice for generics? Is this a case where you think thereā€™s a clear case for generics to just use it, or should you just solve your problems with the specific type if you only need to solve it for one type first, and make them generic later? What would be your thoughts on that?

Yeah, I think I would agree with that.

I thought you liked conflict, Bryan.

Well, yeah, I just like writing programs ā€“ like, keep it simple most of the time. So if you just implemented one thing, then yeah, donā€™t muck around making it generic. Itā€™s only if you find yourself implementing it two or three times, or you want to reuse the same thing in somebody elseā€™s program, and it really benefits from being made generic in that wayā€¦

One of the things that I really, actually, for using that pattern in Go - and it applies to both interfaces and generics, actually, is that you can do that; you can do it for one type. And actually, the changes to make it generic, the changes to make it a user interface tend to be pretty small. You can take that generic code and just like do a global substitution of the type by the type parameter, and - oh, done. Just add a few square brackets here and there and it just works. So I would say thatā€™s a good approach, and helped by Goā€™s syntax and semantics.

[00:34:11.06] Iā€™ve found it sometimes takes a bit of thought to figure out what is the thing that I should be parameterizing. If Iā€™ve sort of fundamentally got a slice of thing, do I parameterize on the thing that is the slice, or do I parameterize on the thing inside the slice? Iā€™m not sure yet if thereā€™s a rule there, but those kinds of questions take a bit of time sometimes. Youā€™ve gotta maybe try it two different ways and see what happens, or start out and see where you get blocked.

Yeah, Iā€™ve actually found an interesting case for that recently, where I was changing an API, and I wanted to change it in a backward-compatible way. And there were basically two types, both of which were kind of set ā€“ one was type XY. So it was like a new type, but had the same underlying type. The old one was deprecated; the new one was new, but we had this function that took the old type. So of course - oh, well, you know, we want to make it check the new type. And it was taking a [unintelligible 00:35:06.18] the type parameter is foo, and itā€™s taking *foo, and then weā€™ll actually do a type conversion inside the function to the new typeā€¦ Which technically should have worked; we were saying weā€™re allowing just this old type and just this new type; we could type-convert between them, but you canā€™t do that. But you can do that if you move the pointer out. Say your type parameter is either *oldtype or *newtype; then you can do the type conversion. So itā€™s little nickles like that which is like ā€œOh, thatā€™s interestingā€, where that kind of decision can make a difference.

So generally then, Bryan, would you say that you are unhappy with the performance of generics, or do you feel like in most cases ā€“

I think I would go as far as disappointed, because I personally, with my background in C++, I sort of expected thereā€™d be more stamping out of different versions of the code specialized to each type, and more opportunities for in-lining, and so on and so forth. And basically, the opposite is trueā€¦ Unless your type is a built-in, like an int or a float. Performance gets a little bit worse when using generics, and methods on genericsā€¦ So I was disappointed by that. I mean, you know, first-world problemā€¦ Having generics at all is vastly better than where we were before. But there are still these kind of corner cases that I tend to inhabit, where youā€™re still reaching for other techniques.

We talked about this a bit before, but is this like thatā€™s forever because of the design, or is this sort of like over time these things will improve under the hood, and we can just wait?

Yeah, I expect it to improve over time, and particularly profile-guided optimization, I think. Trying to not get too deep into the weedsā€¦ The current implementation says that anything where the layout and memory looks the same, i.e. this is always an 8-byte fundamental type, or this is always a 48-byte struct with four things in it, or something like thatā€¦ Anything that looks like that will run the same code. And anything that looks the same in memory will run the same code, is the current implementation. So they could generalize that a little bit to say ā€œWell, we run the profile. The profile-guided optimizer says there are these two cases that we should kind of flatten out into the most performant code, and then every other case is going to still run the same code.ā€ I think thatā€™s eminently doable. Iā€™m handwaving a lot of work onto whoever actually has to implement it, butā€¦ I expect something like that will happen.

It kind of reminds me, Iā€™ve gotta get profile-guided optimization plumbed into our CI pipelines, because itā€™s been available since 1.20. I donā€™t think itā€™s turned on by default in 1.21, so I really should get going on that.

What will that do for people?

[00:38:08.11] Oh, good question. Well, so first of all, the mechanism is basically that you supply the compiler with a profile, in the pprof format; that is a record of what the program was doing when you ran it doing its normal thing. So the compiler can then look at that and say, ā€œWell, I see that 80% of the time in this program was in this one function. So Iā€™m going to change the rules that I applyā€¦ā€ So there are certain rules inside the compiler, for instance when am I going to in-line other functions; and it normally only in-lines really small functions. But if it sees that this one thing is 80% of the whole program at runtime, then it can say ā€œIā€™m going to inline a bunch more things, and Iā€™m going to really change the rules on this one. Iā€™m going to go all out for performance just in this one place.ā€

So the Go team themselves said that the PGL, profile-guided optimization gave them a 6% performance improvement on the compiler, and their benchmarks on the Go compiler. So itā€™s obviously case by case, but itā€™s a little bit more work, because you have to come up with some kind of representative profile. Maybe if you only work in one environment, thatā€™s pulled from your production environment. If you have a wide range of use cases, you maybe use benchmarks and profile that. Soā€¦

Can you combine different profiles, a bunch of different profiles?

Thatā€™s a good question. In general, there are tools that do that. Fleet-wide continuous profiling is a very general case of what you just saidā€¦ And several companies sell that kind of a product. So I donā€™t know whether you can just sort of give six files to the compiler and it figures out what to do, butā€¦ I mean, a profile is essentially a list of stack traces in the code, and sampling counts of the number of times that stack trace showed up. So you can essentially aggregate different profiles just by finding the common stack traces and adding all the counts up.

I mean, to be clear, this is applying to one main program, one binary. So you canā€™t sort of say ā€œOh, weā€™ve got profiles of a bunch of things for this particular library.ā€ That doesnā€™t apply, or is it justā€¦?

Thatā€™s a good question. I think itā€™s matching on the kind of module name, function name, how often that shows up. So it ought to be applicable to libraries, and it ought to be fairly generally applicable. I guess the thing maybe that you donā€™t want to do is supply a profile thatā€™s kind of wildly unrepresentative, because then the compiler will do the wrong thing, make your program at least bigger, which might make it a little bit slowerā€¦

So if Iā€™m supplying a module that other people are using, itā€™d still be worth doing some PGL on that.

Oh, thatā€™s a good question, because generally, people donā€™t use precompiled code in Go. Generally, theyā€™re compiling it all on their target.

So it wouldnā€™t see that if you import a module, for example.

Yeah. So in that sense, it applies more to the main program.

And would you keep updating the profile so that as things change, you keep ā€“

Right, yeah. That would be a good idea. I donā€™t think thatā€™s vital. Like I say, the worst thing that can happen is the compiler kind of optimizes the wrong thing.

That has the potential to be interesting, because the profile-guided program itself will have different profiles, so you kind of need to iterate.

Thatā€™s a good point, yeah. I think that itā€™s at the margins; itā€™s things like ā€“ certainly right now in-lining; I think thatā€™s the main thing that gets affected. But it might in the future do loop unrolling, for instance, based on how intensive this function is used.

Yeah, until we have an AI thatā€™s just doing this all for us, and then we can stop worrying about it and we donā€™t have to talk to Bryan anymore. [laughter]

On the performance point, I know it wasnā€™t planned this way, but I kind of feel like having generics have slightly worse performance for that kind of interfacy case might actually be good for us in the long term, because I feel like it will make it so people donā€™t right now jump into just using generics, where theyā€™re like ā€œOh, well, this is so much faster than interfaces, so Iā€™m gonna use this thing instead of whatā€™s been there before.ā€

[00:42:27.07] So I feel like maybe that in the long term will help us escape the kind of just using this thing because itā€™s faster, just using this thing because itā€™s shiny, and it will keep us solidly rooted in using interfaces, or interfaces that are appropriate, and then ā€œOh, well, I really do have this use case for generics, so I will use it in this place, even though I know Iā€™m paying a performance penalty now.ā€ Even if it might not be true in the future. Like, I assume weā€™re gonna get better with generics, and then they might be faster than interfaces in the future. Or maybe weā€™ll also make interfaces faster in some way.

Yeah, that was precisely what I was trying to get at before, actually. I do think that thereā€™s this pressure, if itā€™s much faster, to use generics, where it might not be appropriate. I think thatā€™s the worry that everyone has, or many people had, about generics just polluting code because ā€œOh, generics are faster, therefore everything must use generics.ā€ You know, you change io.copy, so instead of taking a reader and a writer value, you make it parameterized on the types, which could be faster, right? And it probably would be faster. So why wouldnā€™t you do that? But that means itā€™s actually more complex to use.

Iā€™m hoping that the years of people using far too many goroutines and far too many channels has taught us as a community to not overdo the nice things where we kind of ruin them.

Yeahā€¦ We do hear that a lot, and we do say it a lot, and we talk about that a lot, and I do think thatā€™s important. So yeah, thatā€™s great. Well, before we move on to Unpopular Opinions, are there any other things coming in Go 1.21 that weā€™re excited about? It gets released next month, in August 2023. Min and max - theyā€™re cool. Clear functionā€™s a bit weird, isnā€™t it?

Yeah, I was gonna bring that up. Iā€™m happy that clear function. Itā€™s like, I know it only saves a little bit of code, but having to write those loops over a map to clear everything out was always kind of annoying. I just want this to be empty now.

Yes. Itā€™s weird how it does it with slices.

Yeah, it does something that you sometimes want to do with a slice; it fills it full of the zero value. But itā€™s so different to what it does with maps. So if you have a slice that has 100 elements in it, and you canā€™t clear on it, then you still have a slice with 100 elements in it, but theyā€™re all zeroā€¦ Which I think is a very, very niche case. Most people would expect is they have a zero-length slice when they finish. So I donā€™t really know that ā€“ I didnā€™t read through all the thinking that arrived at that.

I guess itā€™s equivalent to [unintelligible 00:44:52.19] in C, right? So yeah, itā€™s very efficient, because you can use essentially an underlying machine instruction, probably one, to just zero it out just like in one thing really efficientlyā€¦ And that might not be easy if youā€™re using a loop.

I feel like if [unintelligible 00:45:09.01] as well, and you just want to be ā€œIā€™d like all of these things to be garbage-collected, but I still want to use this slice again.ā€ It could be useful for that, just clearing them all out.

Yeah, itā€™s very occasionally useful. Itā€™s just that the same name does something so different with maps and slices.

I guess itā€™s the same with most of those, right? Make, and new, and all of thatā€¦ I guess new doesnā€™t, but make definitely does different things with maps and slicesā€¦ Sort of, sort of.

[00:45:38.04] One thing that I am looking forward to in Go 1.21 is some improvements to generic type inference, actually. So thereā€™s one particular ā€“ in Go, a standard idiom is to return concrete types, but use interfaces. So youā€™re returning a concrete type, but youā€™re actually accepting an interface. But this didnā€™t work for generic interfaces. So you could have like an implementation, a concrete implementation, and you pass it to this generic interface, and say, ā€œYou canā€™t do that. You have to explicitly mention this type parameterā€, even though you can clearly see that one implements the other. And now you donā€™t anymore, so thatā€™s pretty cool, actually.

Yeah, thatā€™s an interesting point though, about ā€œYou can clearly seeā€, because thereā€™s more typing inference that can happen, where actually when youā€™re reading it, you would kind of lose information. And thatā€™s probably a line that you wouldnā€™t want to cross.

Itā€™s a tricky line to choose, and they said they were conservative initially, and now theyā€™re a little bit less conservative. And also, if you have a generic function, it will infer the type of that generic function from where [unintelligible 00:46:47.17] So if youā€™ve got a generic less function that automatically knows how to compare two comparable types, for example, and you pass that to something that expects another generic function, then you donā€™t have to mention, you donā€™t have to instantiate it; it will infer from where youā€™re assigning it to the type parameter for the functionā€¦ Which is also quite cool, actually, particularly in the context of things like slices.sortfunc, and that sort of thing.

So weā€™ve talked about the slices package quite a lotā€¦ Thereā€™s also a Maps package that sort of matches it. It has two or three functions, like keys - it gets you all the keys that have map values, it gets you all the values out of a mapā€¦ Those were things you could do before you just write the loop, but those are little generic functions now that are going into the standard library in Go 1.21.

I want sorted keysā€¦

Well, you can do slices.sort of maps.keysā€¦

It doesnā€™t quite work, because it doesnā€™t return the sliceā€¦ [laughter] Itā€™s probably the generic function Iā€™ve copied and pasted the most, because quite often you want to ā€“ you know, like as a test result, or youā€™re printing something in a deterministic wayā€¦ ā€œI just want all the keys sorted, please.ā€ Like, ā€œOh, damn.ā€ So just copy and paste sorted keys, and usually that strings, but not always.

I am pretty happy about the equal function, because thatā€™s another thing that was kind of annoying to do with a loopā€¦

Right. Yeah. Well, you did have to sort them then, given two maps. You had to get all the keys out, and then sort them, and then check if things were equal.

Yeah. I mean, the sorted keys - if someone perhaps hasnā€™t contributed to Go, maybe they could start a proposalā€¦ There may already be a proposal that Rogerā€™s written, but if not, you could write one, get involved and see what that process is like. Itā€™s quite a nice opportunity. Thereā€™s also clear as well; in that maps package thereā€™s a clear function. Whatā€™s the difference between those two?

Maybe it was there before the clear built-in?

Looking at the docs for the package, it doesnā€™t look like thereā€™s a clear func in here.

Well, there was in the experimental oneā€¦ And it suffered ā€“ I mean, the whole reason why the clear [unintelligible 00:48:59.27] maps was justified was that you canā€™t, again, float nan, not-a-number values. They break the obvious implementation of clearing things from a mapā€¦ Because a nan is never equal to anything.

Not even itself?

No, itā€™s not equal to itself.

So if you try and delete the nan value from a map, itā€™s like ā€œNo, you canā€™t delete that, because it doesnā€™t exist in the map.ā€

Wowā€¦ Who is putting their nans in a map? [laughter]

Who would put nans in floats, right? [laughs]

Well, speaking of that, itā€™s time for our Unpopular Opinions!

Jingle: [00:49:43.26]

Okay, Iā€™ll go first - somebody told me that jingle is too long. Apparently, this has been said a few times; people are like ā€œNo, thatā€™s way too long, that little jingle.ā€ Itā€™s nothing.

The singing is great.

Thanks, Bryan. Thatā€™s really sweet. Youā€™ve accidentally been nice to me. Actually, it was very well put together by the Mysterious Breakmaster Cylinder, who edited that and made it sound good. Itā€™s 25 seconds long, our little jingle. Is that too long? I feel like itā€™s the exact amount. Yeah, whatā€™s going on?

I like it. I like that ā€œYou should probably leaveā€ bit.

Thank you. Yeah. ā€œI actually think you should probably leave. Itā€™s gone too farā€¦ā€

ā€œJust waitā€¦ā€

Does anyone else have an unpopular opinion?

I have an unpopular opinionā€¦ Itā€™s definitely non-techy. My unpopular opinion is that a shower is no good unless it goes properly cold.

What do you mean, you turn it cold, or you just stay in there until all the waterā€™s gone?

Yeah, I always finish by alternating on hot and cold, and it has to finish on cold. And if it doesnā€™t, itā€™s deeply disappointing. I think it was recommended by a physiotherapist once, to stop inflammation and things, and I started doing it. Now I go to someoneā€™s house and I turned it down to cold, and itā€™s still lukewarmā€¦ Itā€™s like ā€œOh, no, noā€¦ā€ I just feel bad. I feel unfinished. Itā€™s just not right.

Do you gradually make it go cold? Like, sort of the opposite of boiling a frog. Or do you just blast it straight immediately cold?

Absolutely blast cold, blast hot, blast cold, yeah.

Yeah. I heard thatā€™s good for your immune system as well.

Itā€™s good for all things.

[laughs]

And lack of it is bad.

Bad for all things.

Thatā€™s a bad start of the day.

Wow. I do like the ice pool thing. Bryan, have you ever had a freezing cold shower?

Well, yeah, when things are broken. Or itā€™s a good example of a bad user interface, where itā€™s a little bit too hot, and you turn it sort of a tiny, tiny amount, and itā€™s freezing cold. Thatā€™s my experience. I do it by accident.

I think if I have the choice between a hot shower that couldnā€™t go cold, or just a shower that was cold, Iā€™d probably go for the cold one.

Iā€™m tempted to get into cold showers, because I hear a lot about itā€¦ And I used to love the plunge pools you get some times in places, where thereā€™s just ice-cold water. You just basically throw your body in it. I find that to be really refreshing. People do all sorts of ice swimming, and things like thatā€¦

Maybe my opinion will become popular with Mat in the futureā€¦

Iā€™m gonna give it a go, thatā€™s for sure. Kris, what do you reckon?

I feel like when itā€™s hot outside I kind of want to do more of a cold shower. Or if I get back from a run when itā€™s been like 90-something degrees outside, Iā€™m like ā€œI just really would like to be a lot cooler than I am right nowā€, so I feel like that can sometimes be good. And I feel like I alternate. Sometimes Iā€™m doing a little bit of cold at the end, it sounds good. But most of the time Iā€™m like ā€œI just want to do a nice, hot shower.ā€ Also, I keep my apartment very cold, so I think sometimes I get that cold by like stepping out of the shower and itā€™s like ā€œOh, okay, now itā€™s just like very cold all at once.ā€

I find it weird ā€“ if I have to have the cold at the end, I actually feel warmer when I come out of the shower. If Iā€™ve had a hot shower, I feel colder. Thereā€™s something about my body saying, ā€œOh, itā€™s cold. I want to keep warmā€, and then you turn it off and itā€™s like ā€œOh, Iā€™m warm.ā€

Yeah, because you feel different. You feel the difference.

Your skin texture is colder, I guess, but you feel warmer.

Yeah, because the outside air is warmer. Thatā€™s cool. Do you do any other weird stuff in the shower? [laughter] [unintelligible 00:53:42.27] No, no, fair enough. I had an ideaā€¦ This doesnā€™t exist, I donā€™t think, but this should exist. And the idea was a little device you could put on your tap, and it has a blue and a red LED. And then depending on the temperature of the water, it changes, and sort of like shines down. So the water is glowing red if itā€™s hot, and cold if itā€™s blue. I donā€™t know if in every country that theyā€™re the two colors that people use for hot and cold. It should be, I feel like. It feels like quite universal, but I wouldnā€™t be surprised. What do you think of that idea? Are you in? Do you want to invest?

[00:54:24.23] Whatā€™s halfway? Whatā€™s lukewarm?

It puts both. Itā€™s a kind of purple. Yeah.

It would have to be. It literally would just be a very simple ā€“ I could get Ron Evans to build this, probably, with TinyGo. It probably wouldnā€™t even need that.

Trickyā€¦ Electricity and water is not a great ā€“

I disagree. They love each other. They get very excited. [laughter] Theyā€™re too friendly, I think, if anything.

Your product liability people might have something to say about thisā€¦

Well, thatā€™s why I donā€™t hire those people.

I do feel that thereā€™s sometimes electricity in that, because you know, you have those obnoxious handsfree faucets that have to have some amount of electricity for the sensor, or whatever. So itā€™s kind of like that, itā€™s just adding some LEDs instead of some sensors.

Yeah. Iā€™ve got one of those taps that does immediate boiling water, which turns out eventually good, because youā€™re not boiling a full kettle. If you want a cup of tea, you can just do it straight from the tap. But then I think ā€œI want that tap in my bath as wellā€, so I can just ā€“

Scold yourself. [laughter]

Yeah, wellā€¦

Yeah, product liabilityā€¦

So you donā€™t want to invest, Bryan. Thatā€™s what Iā€™m hearing. Yeah, fair enoughā€¦ Hopefully it does really well then, and youā€™ll be like ā€œAh, I was the guy that missed out on the LED taps.ā€

Well, I have often thought that a hedge fund which the investment strategy was just exactly whatever the opposite i from whatever Iā€™ve invested in, that would be a great product.

Yeah, thereā€™s another idea I had when we redid our kitchenā€¦ And I wanted to, instead of cupboards, just have dishwashers. Just every cupboard was a dishwasher. And you just put your dishes away, it just cleans them, they stay there, you donā€™t have to pack them awayā€¦ [laughter] Imagine how much time youā€™d save. And I pitched it to the guy that was designing the kitchen. I pitched it as though I was dead seriousā€¦ And he was sort of contemplating, and then they just said itā€™d be really expensive and wasteful to run.

And you probably donā€™t want to wash your cereal boxes, right?

Oh yeah, thatā€™s true. You want other ā€“ thereā€™s other things; well, you could just not turn it on. [laughter] But yeah, thatā€™s a good point.

You can cook salmon that wayā€¦

Is that what you do, Bryan?

Just donā€™t put the soap tablet in.

Donā€™t put detergent in, yeah.

Yeah. Weā€™ll put like a dressing in instead.

Wrap it in foil. Two layers.

Have you ever done that, Bryan?

Iā€™ve heard this, too.

It makes sense.

Iā€™m not gonna try it eitherā€¦ [laughter] If youā€™ve got a huge salmon, itā€™s quite difficult to ā€“ you know, itā€™s not gonna fit in your oven, right? So I could see why people might want to do this.

Yeah. You could take the drawers outā€¦ I bet you could cook clothes, and stuff like that. What are we doing? Weā€™re wasting our time. [laughter] Noā€¦? [unintelligible 00:57:11.17] Kris. How do you cook salmon, Kris?

I donā€™t actually ā€“ I donā€™t eat seafood, so I donā€™t cook salmon at all.

Right. Thatā€™s what I mean, Iā€™m sure you could cook other stuff.

Easy answer.

Also, I donā€™t know if my dishwasher is that much bigger than my oven.

Oh, really? Have you got a small dishwasher, or a big oven? They do tend to be smaller, donā€™t they?

And you might not necessarily be able to pull all of the racks out of a dishwasher, depending on what type of dishwasher it is. It might get a little mad at you. Theyā€™re very intricate machines, very magical.

Yeah, theyā€™re clever. Theyā€™re good. Iā€™ve got one which at the end of its cycle, it opens the door, it pushes the door openā€¦

[00:57:54.02] Ours does that, too. Yes. Itā€™s weird when youā€™re in the room and youā€™ve forgotten that itā€™s on, and you hear that [00:57:56.09].

Yeah. I love that.

If anybody wants a good watch, thereā€™s a guy on YouTube that has not one, but two whole videos on dishwashers and how they work. Thatā€™s not just like a five-minute; these are two hour-long videos on how dishwashers workā€¦ The channel is called technology connections. And itā€™s one of those things where youā€™re like ā€œThereā€™s no way Iā€™m gonna watch this whole thing.ā€ And yet, you will watch the whole thing. [laughter]

Does it cover cooking of salmon, and other fish, orā€¦?

No. But he does scold people for pre-washing their dishes.

Yeah, we need that in the show links, please.

Yeah, letā€™s do that. Weā€™ll put that in the show notes.

Yeah. You learn to not pre-wash your dishes, and not use pods. You should just use like the cheapest detergent you can get, because itā€™s just soap, itā€™s all the same.

This is goodā€¦ The pods are actually worse, unless you use multiple of them, because thereā€™s a nice little pre-wash cycle, andā€¦ Itā€™s a good video, just go watch it.

What about rinse aid? And by the way, when he scolds people, does he use one of those taps that does the water, boiling water, quickly?

Noā€¦ He just looks at you as if heā€™s a disapproving fatherā€¦ Which might be the same. It might burn you in various ways.

Thatā€™s how Bryan looks at me.

Bryan, did you think of an unpopular opinion?

Oh, you mean beyond cooking salmon into dishwashers?

You expressed no opinion on thatā€¦ [laughter]

I wanted to rant about ā€“ just a little short rant about people who seem to want to put the entire program in one line of code. They get the data, and then they filter it, and then they decorate it, and then they map it into something else, and then theyā€¦ Maybe a little bit more in the JavaScript world, or the Python world; itā€™s a little bit more pop ā€“ but I see it. People trying to get that into Go. Just write the loop, please. Just write the thing that does the thing. Donā€™t try and put it inside of ā€“ it doesnā€™t make it any better if itā€™s in a function in a different file. I just have to go read that.

Is this another reason why slices.sort should not return the slice thatā€™s sorted?

Because that enables you to kind of [unintelligible 01:00:08.21] Iā€™ve got this thing, it returns a slice, and itā€™s sorted, and I can have them all in the same expression, deeply nested, sort, filter, blah, blah, blahā€¦

Yeahā€¦ Well, so I guess the implication would be that it should return a different slice. Whereas the one where it doesnā€™t return, the implication is it mutates the one you gave it.

Iā€™d say donā€™t be scared of vertical white space, right? People want to put it all in one line because it looks look simpler, because itā€™s all in one line. But actually, just have a few different lines. You can have a comment.

Yeah. You see, that pattern you see happening with ā€“ Iā€™ve seen it now inā€¦ I did a bit of Svelte.js, which is a JavaScript frontend frameworky thingā€¦ And the way that they recommend you format your code - having attributes inside an HTML tag, on different lines. And it really ā€“ when you first see it, you think ā€œThatā€™s really unexpected.ā€ Itā€™s very common to just have them going horizontally. But itā€™s so much more readable. So yeah, itā€™s like, thatā€™s what I do. And actually, a lot of the formatters do that as well.

I do that with Go function parameters, actually, a lot. Actually, if itā€™s just starting to get a bit long, I just put every parameter on its own line, open brackets on its own line, each parameter separately, close brackets right at the end, on its own line too, and it works quite nicely.

Much more readable. Itā€™s also nice because they line up; all the variable names are aligned in a little stack, which is great.

Yeah, itā€™s great.

But this is not popular opinions, this sectionā€¦

[laughs] I feel like with the Code Golf community it will be unpopular. Theyā€™re trying to minimize on lines, and characters, and all thatā€¦

[01:01:54.10] Yeah. Iā€™m relying on there being a lot of people who like the idea that they can write the whole thing in one line.

I guess that the sort of idiom that youā€™re ranting against really is maybe epitomized by the sort of fluid programming styleā€¦ Or fluent, sorry. Where you have one thing, it returns the same thing, it returns the same thing, and youā€™re just kind of operating on that thing flowing through, so you donā€™t ā€“ yeahā€¦

Yeah, people do that to create little DSLs, and thingsā€¦ And I understand the appeal of it, but almost in every case I find it to be I would rather it was just spelled out in the boring way. Itā€™s just very easy to ā€“ itā€™s much easier to debug things. You can put log statements in between, and things like this as well, rather than being ā€“ yeah. And I think sometimes package developers - they want to really help the people that are going to consume the package, so they do a lot of things, like a lot of extra help, and a lot of work for themā€¦ When actually you arenā€™t necessarily helping. You might as well just let them ā€“ you know, theyā€™re not idiots. Let them do their thing. You donā€™t have to solve every problem.

Yeah. Hard to argue against, when youā€™re in the design phase and theyā€™re like ā€œOh, but this will make it easy for peopleā€¦ā€ I donā€™t think so, but itā€™s a tricky conversation to have, I think, sometimesā€¦

Yeah, yeah. I think so.

I have an unpopular opinionā€¦ I feel like it might actually be ā€“ maybe this time Iā€™ll actually get an unpopular one.

Humble brag.

I do have, I think, the second most unpopular opinion everā€¦

What was that one?

I think it might have been the one where I said ā€œCalling Go Golang is like deadnaming somebody.ā€

Oh, right.

That was very unpopular. People were very mad at me about that one.

Thatā€™s popular with me.

I think itā€™s popular with a certain subset of people, butā€¦

So yeah, my unpopular opinion - itā€™s about analogies. I think that the tech debt analogy - we should get rid of it, because I donā€™t think the thing that weā€™re talking about when weā€™re talking about tech debt is debt. I think itā€™s more akin to malpractice, and people are being irresponsible. Because I think most of the time when tech debt gets brought up, itā€™s like ā€œOh, weā€™re just gonna skip writing the tests, or skip writing documentation so that we can get this thing out the door faster. Or weā€™re just gonna code this in like a really messy way, so it gets out the door faster.ā€ And Iā€™m like, ā€œThatā€™s not debt. Thatā€™s you not doing your job properly. Please just write the comments, and the dots, and the tests.ā€œItā€™s part of the job. You canā€™t cut out vital things. Or if you do, then youā€™re committing malpractice, and we should call it that, and thatā€™s why I think itā€™s gonna be unpopular. So itā€™s not tech debt, itā€™s malpractice.

Do you ever though make technical decisions that are pragmatic? Like, there are ways that ā€“ I donā€™t mean skipping tests. I mean, I do TDD, so I rarely skip tests, and docs; I think thatā€™s all very important. But do you not sometimes think, ā€œWell, this thing could be better, but weā€™re going to just ā€“ itā€™s good enough for now, and weā€™re gonna ship it. But then maybe at some point we have to come back and fix this upā€?

I think if you have a good understanding of the trade-offs, and itā€™s not like a ā€“ like, I guess itā€™s about how much future harm are you going to do in this, and also how much is it of a best practice thing? Like, if youā€™re skipping best practices, then obviously you shouldnā€™t be doing that, so itā€™s not really debt. But I think a thing that might be akin to technical debt is choosing to use a library or framework instead of building it yourself. So itā€™s like ā€œOh, Iā€™ve assessed how long it would take us for us to build it, Iā€™ve assessed the risk of taking on this dependency, and actually using this framework, and all of the knowledge thatā€™s needed for both options, and weā€™ve decided that taking on this framework makes more sense, even though itā€™s more risky.ā€ I think thatā€™s closer to ā€“ especially the way businesses use debt. Businesses arenā€™t just going out and being like ā€œIā€™m gonna go get a big olā€™ loan just for the hell of it.ā€ Itā€™s like, no; youā€™re gonna sit down and assess what are you actually going to use the money for, how are you going to use it, how are you going to repay it, all of this stuff.

[01:06:03.13] So if youā€™re doing all of that math and risk assessment, then what you are doing is likely a debt-focused thing. But thatā€™s rarely, if ever, at least in my experience, what people are doing. Theyā€™re just kind of not doing the things they should be doing, and then being like ā€œOh, weā€™ll just fix it later.ā€ And then later literally never comes, and then they just throw out the whole thing, and theyā€™re like ā€œOkay, weā€™re gonna do it right this timeā€, and then they do the same thing again.

I guess the thing I think itā€™s more akin to is using single-entry accounting for your multimillion dollar company, and then having no notes in your single-entry account. ā€œMoney is going places; where does it go?ā€ ā€œWe donā€™t know.ā€ Itā€™s that level of thing. And itā€™s like, how do you clean up a single entry accounting system and turn it into a double entry accounting system down the road?ā€ Itā€™s like, thatā€™s going to be awful for you. You should never do that. If you know youā€™re going to build a big enough business where youā€™re going to need double entry accounting, just start with it. And itā€™s the same thing with this. If youā€™re not building something, youā€™re gonna throw away in six months, then just write the docs, just write the test code; think about what youā€™re doing. Itā€™s gonna make you go faster in the long run. Youā€™re not gonna get that much speed if youā€™re like ā€œOh, Iā€™m gonna do this, because itā€™s gonna save me like a few hours here.ā€ Itā€™s gonna save you a few hours here, itā€™s gonna make you spend four weeks trying to unwind it in like six months, or less.

How to feel about that? I agree.

For me, a lot of the tech debt ā€“ Iā€™d say the biggest tech debt things that Iā€™ve seen in the past have usually often been because youā€™ve made a new API, for example. Youā€™ve made a new API, and you canā€™t remove the old API, because people are using it. So you end up with two versions of the API. And at some point in the future, you realize that no one is using the old API anymore. But removing it ā€“ maybe youā€™ve written it in such a way that itā€™s really hard to remove the old one. But you kind of want to, because itā€™s holding you back, because itā€™s using loads of stuff that you want to be able to get rid of. So thatā€™s tech debt to me. Youā€™re in this situation of being indebted to this thing of the past, which you kind of had to take on this debt, and you kind of have to pay it sometime. Thatā€™s often the case Like, not just skipping tests. Thatā€™s an easy ā€“ ā€œYeah, weā€™re taking on this. Weā€™re committing malpractice by deliberately taking on this debt.ā€ I suppose. But thereā€™s loads of other cases, I think, where it just arises, because [unintelligible 01:08:29.19] pragmatism, because you have to do this this way, otherwise you wonā€™t make progress.

Yeah. And I think, once again, if youā€™ve done a lot of measured analysis of things where you go into it and youā€™re like ā€œOkay, this is why weā€™ve taken this onā€, I think it can be described as a debt. But I think a lot of the times when people are doing it, theyā€™re not winding up in those situations because of ā€“ I feel like a lot of times, at least when Iā€™ve walked into places, itā€™s like weā€™ve wound up at those places not because people have thought things through, but because they just rushed to do something. So itā€™s like ā€œOh, well this thing is hard to maintain, so weā€™re just going to greenfield it.ā€ And itā€™s like ā€œOkay, but whatā€™s your plan to actually deprecate and dismantle the old thing?ā€ And itā€™s like ā€œWell, we didnā€™t think about that.ā€ Iā€™m like ā€œWell, okay, thatā€™s notā€“ā€ Once again, weā€™re back in the realm of - just because you have itā€¦ Like, you have it now, and you donā€™t like that you have it. Well, you have it because you didnā€™t plan to actually get rid of a thing, but you knew you had to get rid of the thing. That doesnā€™t feel as much like responsible debt usage to me. That, once again, feels like ā€œNo, you should have planned for how youā€™re gonna get rid of it if you knew you were gonna get rid of it.ā€
Obviously, if you need to build this new API for some reason, and youā€™re like ā€œWe donā€™t know how weā€™re gonna get rid of the old one, and weā€™re marking that down as a debt, and we know weā€™re gonna have to deal with it, and itā€™s not gonna be painfulā€ - different situation, right?

But we know how to get rid of it. Itā€™s just gonna take two man months of work, and we donā€™t have that time. Thatā€™s usuallyā€¦ We know how to do it, we know exactly what we want to do, but we just have to pay that debt.

Kris, I bet your finances are in great shape, arenā€™t they?

Yes. [laughs]

Yeah. I thought so.

Iā€™m the person that was like ā€“ to my friends, Iā€™m like ā€œYes, I balance my checkbook every month.ā€ And my friends are like ā€œWhat do you mean balance your checkbook?ā€ Iā€™m like ā€œI reconcile my financesā€¦ What do you mean what do I mean?ā€
I was also the person who was 21, at the bar, just like keeping diligent track of my drinks and how much I had spent, so I would know how much money I had spentā€¦

Even while very drunk, I would do this. Iā€™d be like ā€œOkay, Iā€™m just documenting allā€“ā€ Iā€™d wake up the next morning and be like ā€œOkay, well, I guess thatā€™s exactly how much I drink. Okay.ā€ And then you look at the credit card, itā€™s like ā€œOh, yeah.ā€ So yes, I keep very good track of my finances, yes.

You mean you actually count your change.

I mean, I donā€™t spend cash anymore, so not reallyā€¦ Or I rarely spend cash.

I donā€™t even look in my bank account. Iā€™m basically the opposite of that.

Itā€™s all gone, Mat.

Yeah, basicallyā€¦ Okay, I have another unpopular opinion, another one. A quick one. I get this ā€“ we obviously want to be nice and kind to everyoneā€¦ But actually, in the right places, banter, being mean, poking fun is the way Iā€™ve built my strongest friendships with people. So I actually think that itā€™s not as simple as just always be kind and nice to everyone. I think itā€™s an intellectual exercise sometimes, tooā€¦ Especially if you do it in a way thatā€™s funny, and somewhat uplifting. It can be. So I just donā€™t think ā€“ my unpopular opinion is donā€™t always be nice to everyone, because you miss out.

Be mean to your friends, is that what youā€™re saying?

I mean, I basically am. Kind if. I would hate the idea of upsetting anyone. And I do do that, because thatā€™s a risky take. One time - this is quite embarrassing, but Iā€™ll tell this quick storyā€¦ I was introduced to this guy, and he had a very cool ā€“ the way he was dressed was very cool, but it was deliberatelyā€¦ Almost like dystopian. He looked dystopian in his whole vibeā€¦ Which I really appreciated. I thought he looked great. So he had really sort of tatty clothes, and like scruffy hair, and stuff. He looked great. And then someone introduced him and said, ā€œOh, this is John.ā€ And I just said, ā€œDidnā€™t I give you a pound earlier, outside?ā€ And I donā€™t think he liked it.

So thatā€™s one of those things where Iā€™m drifting off to sleep and Iā€™m suddenly woken again where Iā€™ve said this horrible thing to somebodyā€¦ Take a risk; sometimes it doesnā€™t pay off. But to the right personā€¦ Like, if someone said something like that to me, Iā€™d be thrilled. And I do get it. At the conferences - I was at GopherCon EU recently, and someone said to meā€¦ Last year someone said ā€“ because I talk about my hairline a lot. They said ā€œYour hair doesnā€™t look that bad from a distanceā€¦ From a distance.ā€ Itā€™s like, ā€œYouā€™re quite good-looking in low res.ā€ Iā€™d be gorgeous if I was a Minecraft characterā€¦

And then this yearā€¦ This year someone said ā€“ because theyā€™re joking; they feel like they know me, and itā€™s a complete stranger, but they just said ā€œIs that a wig?ā€ Why would I choose this?! [laughter] Imagine going into a wig shop and saying ā€œOh yeah, how much is that one? Very affordable. I thought it would, because itā€™s tiny.ā€

They clearly thought your hair looks good. I cannot think why, yeah.

Yeah, exactly. It doesnā€™t look ā€“ itā€™s not great. Itā€™s not great, butā€¦ So yeah banter and ā€“ what do you think?

The thing you said about the low res reminds me of that ā€œCute from far, but far from cuteā€ line, which is always like funā€¦ But I donā€™t know how much I disagree with you, because I think in some spaces there is this very large sets ā€“ I think especially within tech companies now, thereā€™s a very large sense of ā€œYes, be nice to everybody, be kind, be civilā€, all of that.

[01:14:11.02] And I think of like the like black or queer spaces that Iā€™m in - like, people are notā€¦ Like, thatā€™s not how things work there. Weā€™re mean to each other all the time. This is not like all people in this community, but a lot of people; itā€™s where the whole like throwing shade comes from, reading people, all of thatā€¦ Itā€™s just like this - yeah, you kind of read people [unintelligible 01:14:29.09] sometimes. Youā€™re just like ā€œYeah, youā€™re still my friend, but what you did - Iā€™ve gotta rip you apart for that.ā€

And I think thereā€™s also this slight level for me where ā€“ I donā€™t particularly like when environments try to be kind to everybody, be nice to everybody, or ā€œWeā€™re welcoming to everybodyā€, because thatā€™s like a little bit of a dog whistle for me that itā€™s like ā€œIā€™m probably not in a safe space.ā€ To be blunt, I guess itā€™s like ā€œThis is some white people nonsense when that happens.ā€ We have to recognize that sometimes people are gonna not be nice, and what are you going to do then? Are you just going to tell them to be nice? Thatā€™s not how this works. Who determines what is nice? Is it you that determines whatā€™s nice? Because what might be nice for you might not be nice for me. So I think thereā€™s a lot of complexity in there. But I think overall, Mat, I agree with you slightly.

Yeah. I mean, those roasts, when they do the comedy roasts of peopleā€¦ Iā€™d love to be doing that. Maybe we could have that as a regular segment. Like, ā€œTodayā€™s the roast of Bryan Boreham.ā€ [laughter]

[unintelligible 01:15:26.06] the whole episode.

Yeah, itā€™d be a new series, that one. [laughter]

But I was listening back to one of the episodes - I think it was a Gophers Say episode where you were hosting, Matā€¦ And all of us were just like roasting you for like the entire episodeā€¦ And that was fun.

Yeah, exactly. Yeah, it was fun. But I think you miss ā€“ if you have this very sterile environmentā€¦ And I understand why this happens in tech companies; of course, we want to make sure that people arenā€™t ā€“ like, you donā€™t want to upset people. But you miss ā€“ thereā€™s a missed opportunity there to build some strongerā€¦ Itā€™s a little bit like a cut, where you get scar tissue on a cut, and itā€™s stronger. That scar tissue is stronger than the tissue there was before. So these little cuts, these little jibes - I think we need it.

The more you explain this, the more Iā€™m like ā€œMaybe [unintelligible 01:16:20.22] Because I think too part of the issue I have with the ā€œJust be nice to everybodyā€ is like, is that really the biggest problem you think we need to solve right now? Itā€™s just like, people are saying mean things, and Iā€™m like ā€œThatā€™s not the biggest problem that I have certainly had in a lot of these tech spaces.ā€ I would just really like it if people werenā€™t doing racist things all the time. And itā€™s not them saying things, itā€™s like other things. So I think sometimes we focus a little bit too much on the ā€œOh, just say kind things to each other, please.ā€

Right. Yeah. Itā€™s almost worse by just ā€œNow at least weā€™ve solved this problem, because weā€™re all saying these right things.ā€

It reminds me a bit of a few years ago, when there was a really big push to get rid of certain words that we use in tech, like whitelist, and blacklist, and master, and all of thisā€¦ And people are like ā€œWell, itā€™s really painful for people of color to have to see these words, and all of this.ā€ And Iā€™m like ā€œBlack people were just like ā€“ what do you mean?ā€ Like, seeing the word ā€œslaveā€ is not throwing me into an existential crisis, or anything. Itā€™s a thing that happened. But also, this usage of master, is not different; whitelists and blacklists have different ā€“ like, words can mean multiple things. So itā€™s like, this feels really weird as a thing for us to be focusing on right now, especially when itā€™s like, there are much bigger problems that we should probably be looking atā€¦ And there was like a non-insignificant amount of effort that went into ā€œLetā€™s go through all the codebases and remove master. Letā€™s go through all the codebases remove blacklist, and whitelist, and all of thisā€, and I feel like after that people were kind of like ā€“ itā€™s kind of like after the election of Barack Obama, like ā€œOh, no more racism. We got rid of all the stuff.ā€ But it was like, ā€œThatā€™s not the stuff. Thatā€™s not the thing.ā€ I think itā€™s kind of the same with this ā€œOh, everybodyā€™s being nice and civil and kind to each other right now, so thereā€™s clearly no problems with other stuff.ā€ Thatā€™s not how that works.

Yeah. On a level, yeah.

But Roger, youā€™re quite a nice guy. Are you ever mean to people?

Never. [laughter] Only my friends.

Exactly. Your closest friendsā€“

We definitely have some good banter, yeah.

But you mentioned this, Kris. Sometimes ā€“ I mean, I think itā€™s really valuableā€¦ A joke thatā€™s a jibe can be a really kind of good way of actually people getting some feedback. Like, Iā€™ve actually ā€“ you know, thatā€™s how we do it. If someone ā€“ if theyā€™re being big-headed or something, the punishment, the social kind of reaction to that is often a joke, or poke fun at it, or something like thatā€¦ And itā€™s kind of a nicest way, or a very nice way, in some ways, to deliver that bit of feedback. And itā€™s kind of light-hearted, and itā€™s non-serious.

Many a true word is best said in jest, right?

So it might sound like banter, but youā€™re actually being mean.

Well, I think itā€™s sometimes a good signal. And it gets you thinking. But itā€™s a safe way to do. Humor is often a safer way. Bryan, you called a lot of people idiots today on this podcast, so I assume youā€™re on board with this. [laughter]

Individually, by name. Yeah.

Yeah, weā€™ll cut it out. Weā€™ll cut out all the names. Thatā€™s brutal. [laughter]

Iā€™m just sitting here thinking that there are a lot of cultural differences, and that really in a bigger company tends to be a thing that you need to watch out for, and in a broadcast medium you have to go to the lowest common denominator. That makes it harder. But I do love the sort of ā€“ well, for meā€¦ Now Iā€™m going to insult more people. So the sort of American thing of ā€œEverything is awesome!ā€ All of the ā€œFantastic!ā€ If itā€™s not fantastic, then you must hate it. You know, ā€œHey, I fixed that bug.ā€ ā€œFantastic!ā€ Right? And the British thing is more ā€œYeah, itā€™s alright. You could do better. Yeah, fair. Yeah.ā€ And I really love many of our Eastern European colleagues who just say ā€œThis code is s**t.ā€ [laughter] Theyā€™re just absolutely straight out with ā€“ for the same code, to be clear, in each case.

Yeah. I feel to Eastern Europeans, the highest compliment they can give is like ā€œGood. Itā€™s good.ā€ And youā€™re like,

ā€œOh, okay.ā€ [laughs]

Once every five years, yeah.

But the other thing going around to conferences and stuff Iā€™ve noticed is that because in a way weā€™re all selected around this language, so weā€™re all kind of in software, a lot of us like building thingsā€¦ So I think thereā€™s a certain level of ā€“ I donā€™t know what it is; thereā€™s certain level of intelligence you can kind of assume with technical people. Or itā€™s whatever the Go community does that attracts people to it, I donā€™t know. But I find that wherever I go, some jokes just work everywhere. And that was a big surprise to me, because I was very conscious of different kinds of cultures, and different approaches to things. But I do find that you can kind of have ā€“ we just have a lot of fun with people. Anytime Iā€™ve interacted with groups in the Go community, in tech communities, it tends to be a really high level of kind of really good, quality sort of interacting. Only sometimes ā€“ well, like I said, people make fun of my hair, because I make fun of it on stage, and stuff. But itā€™s fun, itā€™s nice.

[01:22:10.15] So what kinds of jokes do go down well, universally? Iā€™m interested, given that Iā€™m giving a talk at [unintelligible 01:22:14.14] in Italyā€¦

Yeah. Well, in the conference audiences, a lot of them listen to Go Time. So thatā€™s different, because they sort of expect it now. One of the big things I noticed is you have to let people know that itā€™s a joke. You canā€™t just say something thatā€™s hilarious, that we might think itā€™s hilariousā€¦

Arguably hilarious.

Yeah. But if they donā€™t know itā€™s a joke, theyā€™re probably not going to just sit and laugh at you, because they might consider that to be quite rude. So standard office humor works at conferences. I donā€™t do it, but things like ā€œOh, forgive this code. I wrote it on a Monday.ā€ That will get a laugh. Or if you say, ā€œOh, I probably did this before Iā€™d had any coffeeā€¦ā€ These sort of things work, because theyā€™re safe. Theyā€™re a bit like - we have these Christmas crackers in the UK, and they always come with a little joke that is just terrible. Theyā€™re terrible jokes. And itā€™s almost like youā€™re united in the eye-rolling against these jokesā€¦ But itā€™s safe, they know itā€™s a jokeā€¦

I said once at a conference that my dad had said, ā€œOhā€“ā€ Yeah, heā€™d said something that I canā€™t remember what it was. And I just said, ā€œGet out, dad.ā€ Right? That was my thing. Which, to me, that was really funny. And it was just silent. Everyone just thought I was telling my dad to get out. So itā€™s like, it sometimes doesnā€™t work.

Yeah, I feel like the broader thing is just youā€™ve gotta have a lot of nuance with this, right? I think sometimes in these types of spaces, or in communities, or I guess in the world in general, itā€™s like, people want to have one easy way thatā€™s like universally true, objectively. Like, ā€œEverybody should be nice to each otherā€, or kind, or these other very positive words. And itā€™s like ā€œWell, I mean, thatā€™s not possible.ā€ Thereā€™s gonna be some people who are gonna be not nice, or not kind. But itā€™s also just infeasible, since what is nice from one personā€™s perspective is not nice from another personā€™s perspectiveā€¦

Thereā€™s the whole thing about Southern people, where if they say ā€œOh, bless your heartā€, itā€™s like ā€œAre you saying that in a nice way, or are you saying that in like the ā€œnice wayā€? So itā€™s like, the very same words, said in the very same way, could mean two completely different things. So I think itā€™s more like weā€™ve gotta be like, letā€™s navigate these situations better, and letā€™s have ways of like, if there is harm thatā€™s done, repairing that harm. Focus on that, and making sure that itā€™s like ā€œOkay, thatā€™s a line weā€™ve crossed. Letā€™s make sure we donā€™t cross that line again.ā€ But I think when people start getting into the dogmatic universality of like ā€œDonā€™t tell jokes about thingsā€, or donā€™t do this, or donā€™t do that, itā€™s kind ofā€¦ I donā€™t know, thatā€™s a little too much; this pendulum has swung a little bit too much to the other side.

Yeah. And we should forgive people as well if they do cross those lines, especially if itā€™s a joke. It depends, but if itā€™s coming from a good place, and itā€™s too far, or whatever, I do think we need to be a bit more forgiving, rather thanā€¦ I sometimes get DMs, and itā€™ll just say, ā€œMat, no.ā€ Itā€™s just like what you might say to a dog. So I get that, and Iā€™m just like ā€œAh, come onā€¦ā€

I donā€™t like the concept of throwing away humans, or like being like ā€œYou did something bad. Youā€™re gone forever.ā€ Itā€™s always irked me a bit. Even with things where Iā€™m just like ā€œI donā€™t like you as a person at all.ā€ But stillā€¦

Yeah, you still do a podcast with me.

Iā€™m not saying you specificallyā€¦

Oh, right. Not this time.

ā€¦Iā€™m saying ā€œyouā€ in the general. I mean, I find ways to poke fun at youā€¦ I made a whole little TikTok about you, that maybe one day will get posted, because I think itā€™s hilarious.

[laughs]

Yeah. Weā€™ll put it in the show notes.

Iā€™ll install TikTok for that. [laughter]

Oh, a plug - we do actually have a TikTok. I found out. Iā€™m on the TikTok. I didnā€™t know. I thought it was just like I never had anything posted about me on TikTok, but thatā€™s a lie. Thereā€™s lots of videos on me on TikTok.

Oh, wow. I didnā€™t know that either.

Go check out Changelog.com. Itā€™s like @changelog.com at TikTok. Weā€™ve got a nice little TikTok page.

Oh, wow. Nice. Okay, well, on that bombshell, itā€™s time for us to wrap this up. Weā€™ve gone way overā€¦ But this was great. I hope theyā€™ll keep this in. Thank you so much for joining us to talk about generics. Roger Peppe - always a pleasure. Hopefully youā€™ll come back again soon. Bryan Boreham - again, we should maybe do some more performance-specific episodes. That would be really great to talk to you, pick your brains on that a little bit more as well. And of course, Kris Brandow. Thank you very much, see you next time on Go Time.

Changelog

Our transcripts are open source on GitHub. Improvements are welcome. šŸ’š


About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK