Runtime Arguments

9: Looking at Data Types From Both Sides

Jim McQuillan & Wolf Episode 9

We talk about data types and their importance in software development. Modern dynamic languages hide type information from you but it's still there, under the hood. Statically-typed languages, on the other hand, bring types right out in front of you. What are the fundamental types and why are they important? What about user defined types and aggregate types?

Join us as we dive right in and try to explain it all. In most episodes, one of us (we alternate) has knowledge or does research and presents the most helpful information they can, while the other asks questions. This episode is mostly Jim, but more a combined effort than usual.

Takeaways

  • The CPU knows about (let’s call them “atomic”)  types and has instructions that apply to them
  • Languages know about types BEYOND what the CPU knows and provide operations beyond what the CPU can do
  • In Strictly typed languages, the compiler can catch a whole suite of bugs that you may not catch in a dynamic language until runtime. (because you made a promise, and then you broke it)
  • You can build your own types that are vastly more complicated than the CPU or Language provide

Hosts:
Jim McQuillan can be reached at jam@RuntimeArguments.fm
Wolf can be reached at wolf@RuntimeArguments.fm

Follow us on Mastodon: @RuntimeArguments@hachyderm.io

If you have feedback for us, please send it to feedback@RuntimeArguments.fm

Checkout our webpage at http://RuntimeArguments.fm

Theme music:
Dawn by nuer self, from the album Digital Sky

Wolf:

Howdy everybody! It's another episode of Runtime Arguments. I'm Wolf, and my partner, as always, is Jim McQuellen. Hey Jim. Hey Wolf. Um today uh we are gonna talk about types. Um the word types probably made you want to change the channel, but it's actually really cool. There's lots of different facets to types. Types mean something to the CPU, they mean something to the language you're in, they mean something to the human beings who are reading your program, they mean something to you when you're compiling. I think there's a lot to say about types. Um we're gonna start at the bottom and work our way up. Uh this is gonna be an episode where uh we both do a lot of talking. Um so uh at the beginning, uh Jim knows a lot about machines and CPUs. I know a lot about languages. Uh I think it's gonna be uh I'm pretty pleased with what we're gonna s we what we're gonna say today. Um as always, uh we care about your feedback. Uh in a in a little bit, we're gonna talk about some feedback we've had to some previous episodes. Uh, and at the very end of the show, we're gonna reiterate how you can best give feedback. Uh I'm gonna say it right now: the absolute best way to give us feedback is email to feedback at runtimearguments.fm. Um and in fact, uh speaking of recent episodes, uh, I am super pleased to say that uh our most recent episode, the one on AI, had more downloads in two weeks than any episode we've done yet. And uh people have actually come up to me uh at the office and in user group meetings and whatnot uh to talk about it, to tell me their opinions, both good and bad. Um but before we talk about any feedback, uh let's uh let's talk about us. Jim, how how'd your week go?

Jim:

You know, it was a it was a busy, busy week. I got a lot of work done, and I actually got to try some AI stuff. Uh I'm super glad about that. Wolf impressed upon me that I should. And uh so I uh I have an account uh to use Gemini because we we're a Google workspace or w whatever they call that thing, workspace, workplace, whatever. Anyway, we have an account to use Gemini Pro. So I gave that a little bit of a try, and it was kind of interesting. I asked it to generate a Sudoku solver in Perl. And it took a few seconds and it spit out this maybe 75-line Perl program. Oh, that's pretty cool. So I cut and pasted it into a into a file, made it executable, and I ran it and it blew up. Uh syntax error. I looked at the code, and there was a couple of places it was trying to dereference a scalar that wasn't a reference at all, and it died.

Wolf:

So I went back to Gemini and which you noticed because you're a domain expert.

Jim:

Yeah, yeah, okay. Uh I I I fixed the bug because it it was obvious what was wrong. So I fixed it and I ran it, and it was great. But I went to I went back to Gemini, and because Gemini and and these AIs, Claude and the rest, they're conversational. Um I said, hey, your program has a bug in it. It's trying to dereference something that's not a reference. And it was funny because, first of all, it apologized, and then it told me I was smart and thank you for for finding the bug, and it chewed on that for a couple of seconds and produced a new version. It said, here's a new version. This one doesn't have that bug. And I copied that into a file and I ran it, and that one worked, so that was kind of neat. Uh I my question is, why didn't it give me the bug-free version to start? That that kind of surprised me. Uh, but it was interesting. And I I also used AI to uh, you know, I I do a lot of Googling, and I've I I've changed my way I pose my questions. Uh I I I I saw a preview for a movie, or it wasn't even a preview, it was just a clip on one of the one of the social media sites on a movie, and I uh Russell, no, not Russell Crows, somebody else was in it. Um I can't even remember right now. But uh I I just went to I went to Google and I typed in uh uh what's the movie about the the old west uh uh soldier who is tasked with taking a Indian chief back to his uh uh home grounds in Montana. That was all I said. And immediately it replied back and it told me uh the name of the movie and who was in it, and uh that was cool. That that's not how Google used to work, and I think that's just because of it's got Gemini built in, and it it sort of changed how I think about asking my questions now. I don't try to ask them as a programmer, I try to ask them more as a human, I think. And it was kind of neat. Anyway, how's your uh week going, Wolf?

Wolf:

Uh my previous week uh has been so astoundingly busy. I'm always working on productivity and trying to uh not just get more stuff done, but get of the things I have to get done the most important, most move the needle kind of stuff done. Um and I'm not doing this very scientifically, I'm making lots of changes at once. Um, you know, what hours I sleep and when I commute and how much exercise I'm getting and how I prioritize. I'm changing it all at once, and so last week was really successful, but I don't know why. So that was uh that was uh unfortunate for me. I'm feeling good that I'm getting more done. Um but uh I'm a programmer, I want to know why. That's I I hate the kinds of bugs where they just suddenly go away and you don't know what was wrong or why it why it ever worked or why it doesn't work now or why it works again, or I feel the same way about my productivity. So that was my previous week. Feeling good about stuff done and less good about understanding how I got stuff done. Um but let's get into the feedback. Um like I said, we had some overwhelming response to this uh AI episode. Um what have what have you gotten back, Jim?

Jim:

Um well we we we got several emails back from people, and they were all uh uh really enjoying the article, or the the uh episode rather. And um and so that was nice to see. And you know, not exactly feedback, but I uh this is related. I did I read an article uh about how uh the free as uh free BSD project. Uh they've got a proposal out there that says they shouldn't accept any contributions generated by AI, including source code, documentation, commit messages, and because the LLMs are unable to provide the necessary assurance that the generated material is compatible with the free BSD license or that the material has been appropriately attributed to the original authors. Um I think that's pretty interesting. Uh I'm not sure if this proposal will actually get approved, but uh if you're if you're contributing to the free BSD project, um it it's it's pretty interesting. You're not supposed to use AI in any portion of your contribution. Uh whereas uh the Linux kernel team, um, they do accept AI-generated source code and documentation, but must still meet the strict quality uh and style standards that uh that all contributors uh uh must must meet. Uh and they have to be transparent about the fact that it was generated generated by AI, and contributors must ensure that AI generated code doesn't violate any copyright or licensing agreements. I don't know how you're gonna do that. How do you generate something with AI and be uh certain that it's not violating anybody's copyright? Uh that's interesting.

Wolf:

Um Yeah, um of those two things, I I feel like I'm more on the side of the uh Free B SD proposal than I am on the Linux side. Um because I I just feel like you can't necessarily prove that what you're adding is uh licensed correctly, safe, and attributed. I don't think those things I feel like the FreeBSD guys got it right.

Jim:

I I think so, except that contradicts something that you said during the episode, and that was you use uh uh AI to generate your commit messages. Well, the Free BSD guys are saying you can't even do that. So I guess you're not contributing to the Free BSD project.

Wolf:

Or when I do, I'll write my own commit commit messages. Yeah. The reason like I feel like that's okay is um that there's uh the repo things come from and there's the product you're delivering. And if a commit message you got help from AI, well, that's in the repo, yeah. But it's not part of the shipping product. It doesn't contribute at all to the shipping product. So I feel like that's an edge case. Is it okay or not? Yeah, I I I haven't really thought about it enough to to have an answer to that.

Jim:

Okay. I'll I guess I'll accept that. And I I I think the FreeBSD guys I I I side with them as well. Um we'll we'll see how it shakes out if that proposal actually uh gets approved. Uh I think that's pretty interesting.

Wolf:

Um I got some feedback.

Jim:

Yeah, okay.

Wolf:

Uh I got some feedback in person uh from somebody I really respect, uh who's really smart, and he listened to the whole episode. And uh I think the episode was long, but I made I made two pretty important points. Uh one of the points is AI doesn't give you the best answer. Uh it certainly doesn't give you an answer that's better than anybody has ever given before. It gives you the most popular answer. Um and the second thing I said was that um to to have success with AI, you you need to I'm I'm gonna use the words domain expert, but you need to be able to look at the end product and know enough to know does it solve the problem? Is it correct? Does it have weaknesses? You've got to understand what you made. And maybe you made it together, and maybe AI made it entirely by itself, but if you don't if you can't prove that it does the right thing, um, you're not gonna have a very good day. So those are the two things that I thought were the biggest takeaways from the AI episode, and this smart guy that listened to the episode, um he liked the episode, but he said, his conclusion was, but your points were maybe valid for a person like Jim who hasn't used it yet, but everybody else already knows what you said. Uh and I felt like um no, people don't know this. There are people who think AI is their girlfriend, or that it's actually thinking, or that it's predicting the future, or it's it's giving you the best possible answer. So yeah, yeah, uh I think there's all there are smart people who didn't need to hear the things I said, but my feeling is a lot of people did. So that was the feedback I got. Anyway, enough about AI. Jim, let's talk about types.

Jim:

All right, thank you. Well, um, you know, before we can talk about types, we have to spend just a few seconds talking about uh uh some some units of measure uh and what they mean. Uh you know, a bit, it's the smallest uh piece of data that a that a computer can know. It's a zero or a one, right? Um it's a binary thing. Uh bytes are made up of bits. A byte is eight bits. Uh then there's this thing called a nibble, which is four bits, but in all my years I've never used a nibble. Uh, you know, I might think of a nibble as one hex digit in a in a hex string, but you know, what else? What else is a nibble? Um and then words. Uh words are made up of some multiple of bytes, uh, and it really depends on the machine architecture, the CPU architecture. Uh if it's uh if it's a 16-bit processor, a word is likely going to be 16 bits long. Uh if it's a 32-bit processor, it's a 32-bit word. And of course, a 64-bit processor is guess what? 64 bits. Um we don't talk much about words either. You know, it's really about bytes, I think. Um let's get into the hardware a little bit, though. Uh, the hardware, the CPU, it knows about these things. Uh, it knows about uh there there are integral types. I'm gonna talk sort of in terms of a C programmer, uh, because I did an awful lot of C programming a long, long time ago. I haven't touched it much lately.

Wolf:

Can I actually say the thing about C that um it's the thing they said when C first came about. And that is C was written to be a portable assembly language.

Jim:

Yeah. Yeah, an assembly language, uh, you know, for those that that haven't used it, that's like the closest you'll ever get to a CPU. At the assembly language level, you are talking uh about machine instructions and and things that are really specific to that CPU. So you would write different machine instructions for a uh x86 architecture than you would for uh for an ARM or for a risk uh CPU or or really any of those uh CPUs, they all have different instruction sets. And at it at the assembler level, that's what you're you're talking. Uh at the C level, as Wolf pointed out, that's a portable assembly language. Uh at the C level, uh everybody talks the same. Doesn't matter what your CPU is. Um but you know there are some uh there are some basic types that uh that C knows about and and the hardware knows about. So we'll you know I'll point out that there's uh there's a uh character, uh C-H-A-R, car or char. I'm never quite sure how to how to pronounce it. How do you pronounce it?

Wolf:

I guess I say it different than everybody because I say care.

Jim:

Care. Okay, I I guess I say it that way too when I say it. Um uh that's eight bits, right? Um uh then you get into your integers. Uh an integer, uh you know, uh Wolf pointed out a couple of weeks ago when we started talking about this episode that uh that an integer size is generally the natural size of the registers of the CPU. I did a little bit digging, and and and that's not what I found. Um uh registers, or uh not registers, but uh an integer in an x86 uh 64, it's a 64-bit processor, integers are only 32 bits long. Uh Raspberry Pi, that's an ARM chip, again, 32 bits long. Uh a Mac, I've got an M1 in my uh studio, and that's 32 bits. I kind of thought those would all be 64 bits, but they're not.

Wolf:

I I will point out that uh in these CPUs, um, yes, the CPU registers are wide, 64 bits, but all of the CPUs that you just named have operations that work on the entire register and also just half of the register.

Jim:

Yeah, a lot of the registers, there are there are general registers in these processors, and they're 64 bits wide. Uh but then those registers actually have have uh uh uh they can be looked at in pieces. You you know, in a s in a 64-bit register, you can look at it as two 32-bit uh uh there there's a name for that register, and it references the either the first 32 bits or the second 32 bits. And there's also breakdowns by 16 bits. Uh, but the the general registers are 64 bits long, uh, but for some weird reason, ints are 32 bits. Uh then you got you you've got like uh uh little adjectives you can put on these uh uh when you declare them in C. Uh you've got a short int, uh, and that would be 16 bits. Uh a long int, there is your 64 bits. And interestingly, there's a there's a type called long long int. That's also 64 bits. Uh I don't know why it's not like 128 bits. It seems like if a long is 64, long, long ought to be longer. But it's not. The C language has this interesting specification, and let's see if I can get this right. Uh it doesn't really make any assumptions about the size of a short, an int, or a long. I think the specification says a short shall be no longer than an int, and a long shall be no shorter than an int. It's possible they're all all three of those are the same size. Uh I think by convention, though, uh now uh uh shorts are 16, ints are 32, and longs are 64. Um C99, which is long after I started uh uh after I was programming in C, C99 added a bool type. It's actually underscore capital B O O L. Uh interesting, that takes eight bits, even though it's only got a value of zero or one. And the cool thing is if you put any other value into a bool variable, it's still gonna have either a zero or a one. If you put a zero in, it's gonna be zero. If you put a three in, it's gonna have a value of one. I thought that was kind of weird.

Wolf:

Okay, now I have a question.

Jim:

Yeah.

Wolf:

Um so I can see two possibilities for a bool. Uh one is that any non-zero value is true, and the other is that it's only looking at the le lowest level, the lowest bit. Um so three is true because the the zero bit is set. But would two be true? That's my question. I actually don't know the answer.

Jim:

I I I'm I'm guessing that's uh uh machine specific, but uh if you were writing the microcode to process that, you may just look at the at the the leading bit to see what it is, you know, because uh uh uh a one is only one bit long and and you know, zero or one. So if it's uh if it's zero is zero, if it's one, it's it's true. Um a two is uh binary one zero, leading bit as one. A three is binary one one, leading bit as one. A four is binary one zero zero, again, leading bit as one. Uh we could spend all day running on this, but uh um I I thought it was interesting. And we're gonna talk about structs a little bit later on, but a struct is something you can use to to combine uh data uh uh data types. And so Wolf sort of uh posited the the uh assumption uh that if you put a couple of bools into a struct that maybe the struct would only be eight bits long. Uh no.

Wolf:

If you are there are some languages where you can make that be true.

Jim:

Okay. Uh well in in my testing, what I found is if you put three uh bools into a struct, that struct is 24 bits long, three times eight. So I I thought that was interesting. Um aside from uh those uh integral types, uh care in tool, uh floating types. Uh if you got to do floating point arithmetic, there's a float, there's a double, and there's a long double. A float is uh 32 bits. Um it uses something called the IEEE 754 single precision binary floating point format. Um now that came out in uh let's see, in 1985. Again, I was programming a C before that. I've been doing this a long time. Uh, so that was even before the IEEE 754 spec. Uh, but now pretty much everybody's using that IEEE spec. And there's a 32-bit version, a 64-bit version, and 128-bit version of that spec or format for that spec. Uh a float in C is 32 bits, a double is 64 bits, and a long double is 128 bits. So now we're getting into the 128 bits. That's uh what was that, 16 bytes? Is my math right? Um one piece of data taking up uh uh 16 bytes. That's that's kind of neat. Um anyway, these types are important to to the compiler because it it uses that to generate machine code that actually runs to generate the uh the uh uh instructions um that that your program will run with. Um another type that that if you're a C programmer, you run into this all the time, and that's pointers. Uh pointers are 64 bits on on these uh uh systems. Uh but it's important to note pointers are not integers. You might want to treat it like an integer. A lot of people do. They should not. Um uh they're they're they're they're they're pointers. They're not integers, they're pointers. You can do arithmetic with them. Um something I didn't mention earlier though, with uh back to the uh integral types is um uh with with uh integers you have signed and unsigned. Uh and all they do with integers uh is they they uh set the the most significant bit to a one if it's negative. Um and it would be zero if it's positive. Uh so you know go back to an eight-bit uh byte, um that can hold it it's eight bits, it can hold 256 different possibilities, right? So it can hold uh if you're talking about uh unsigned, it can hold from zero to two fifty-five. That's that's the types of numbers you can fit into that space. Um if it's signed, then it's uh what is it, uh uh 127, a positive 127, a negative 128, I think. Um that's the range of values you can store in that. Uh 60, uh 16-bit, it's a larger set. Uh 65,536 uh is the uh from zero to sixty five thirty five is the range of uh values you can store in that. Uh 32-bit, it's four four million something, right? Is that right? Four million, four billion.

Wolf:

I think it's bigger than millions.

Jim:

That's four, four billion.

Wolf:

I hate big numbers.

Jim:

Yeah, four billion. But if it's signed, it's gonna be half of that, right? It's gonna be two billion something positive, two billion something negative. Uh it it it's kind of exhausting. But uh it's it's uh that that's how the computer does its thing with all these different uh uh types internally. Um let's talk just a little bit about the floating point numbers. Um uh the IEEE spec. Uh it defines several things. One of them I was really surprised about. If you ever work in JavaScript and you have something that you treat it as a number and it turns out not to be, uh you get the value of N-A-N, capital N little A, capital N, not a number. That's an I think 754 thing.

Wolf:

If you have the value NAN in JavaScript and you use the type function on it, the thing it tells you is that it's a number. I think that's it.

Jim:

I'm not sure my life has. Even though uh so what you're saying is not a number has a type of number. That's what I'm saying. Even though it's not it tells you it's not, uh, but but JavaScript will tell you it is. So that that's kind of interesting. Um the IEEE uh 754, it defines the interchange formats, uh rounding rules. That's important that everybody do rounding up or down. When you're when you're dealing with floating point, um you're gonna have to round numbers somewhere along the way. Uh the IEEE spec defines what those rounding rules are. Uh, like 7.5 if you round it to an integer, is that seven or eight? Uh the rules are are in the IEEE spec. Uh it also handles uh exception handling. Uh what happens if you divide by zero? Right? That's an exception. IEEE spec tells you uh uh that that's a that's an exception. Uh overflow. What happens if you try to stuff a number into a variable or into a into a uh uh uh a piece of memory and the data type uh doesn't hold that number? Um I I know this isn't floating point, but you know, if you look at uh uh a character, eight bits, and like I said, it holds from zero to two fifty-five. What happens if you put 300 into it? Right? You got overflow. Uh the uh the CPU doesn't care much if you do that. It'll just give you uh uh weird behavior.

Wolf:

I wanted to uh mention something when you talk started talking about nan, I was immediately uh reminded of null in uh database stuff because two nans are not equal no matter what, even though they are the same thing. And any uh expression that has a nan in it, no matter what, the answer to that expression is nan. Um so it's not equal to anything else, right? It's not equal to itself, and every use of it leads to another nan, um just like null in a database. Almost just like null in a database.

Jim:

It is, yeah. Null in a database confuses people. Um if you try to compare something to null, uh unless you're looking specifically for null, but if you try to compare a variable to null, that that comparison is false. No matter what. If you're comparing anything to null, and I think even if you compare null to null, it's gonna be false. Um so that's yeah, that's a lot like not a number. Um if you um uh well we talked about uh overflow, um, but let's talk about not overflow, let's talk about alignment. Uh this is important in a in a CPU, uh data alignment. Um and what I what do I mean by data alignment? Um you know, we talk about uh 8-bit by 16-bit and 32-bit values. Um if you try to do any operations on some of these values, um they have to be aligned on a on a word boundary many times. Uh with an x86 CPU, they can be aligned on an 16-bit or 32-bit or 64-bit boundary.

Wolf:

Where by alignment you mean that the address in memory is divisible by that number.

Jim:

Yeah, the address in memory is a multiple of that. So if it if it needs to be aligned on a 32-bit boundary, that means that uh if you let's say you're starting at zero, if you store a byte there, uh it's gonna start in in the first uh eight bits, and the next uh uh the next uh 24 bits are gonna be wasted. So if you try to store another uh uh uh well if you try to store a word after that or a you know a 32-bit after that eight-bit, it's gonna store that 32-bit uh value uh uh starting at position three, right? Four. Starting at position four.

Wolf:

Right.

Jim:

Yeah. Uh 0, 1, 2, and 3, that's 32 bits. That's gonna be your first variable or your first uh your first bit of data. If you try to store a 32-bit value after that, uh it's gonna start in position four. Um and this is gosh, programmers don't don't think about this stuff anymore. Um and I kind of think they should. Uh back uh years ago when storage was was expensive. Uh you know, now you can buy 16 terabyte drives for a couple of hundred bucks, right? Uh but back uh when I was starting out, uh this is my old guy rant uh being turned on right now. Uh we used to uh I used to do a lot of COBOL programming, and we used to lay out records in COBOL, and we were really, really careful about laying out that record so that everything uh would fit in the least amount of space. So like you didn't you didn't store a byte and then a 32-bit value and a byte and a 32-bit value because that would take uh what I just described there would take uh uh four 32-bit chunks of memory, right? So four 32, 100, that would take 128 bits, even though it's only uh 8-bit. It's two 8 bits and 2 32 bits. It seems like it should add up to um uh what is that, seven uh 80? No, it takes 128 bits to store that.

Wolf:

Uh because you got to be able to do that. So you use the word alignment, yeah. Uh, and alignment is the cause and the effect. There's a special word for that too in languages. That word is packing. And um C has a rule that it lays out the variables in exactly the order that you declared them. And some other languages, I'm looking at you, Rust, uh, have the opportunity to rearrange the values uh so that they pack tighter together. Rust has to obey the same uh underlying machine laws that C obeys, like alignment and packing. Uh but unless you specifically tell it, I need this to be compatible with C, Rust is allowed to move things around to give you the best answer.

Jim:

That's pretty neat. Uh you know, back in my day, we didn't we didn't have that. We had to specifically say the order that you wanted things. And what made it even more important, like I said, storage was expensive. Um the thing you had to worry about back then was the sector size on the disk. And I uh uh my cobalt days, I was dealing with uh Texas Instruments uh Business System 800. And the sector size on the discs on those was 768 bytes long. So very much like alignment, uh if we stored uh 768 bytes, that would fit into a sector beautifully. It was fast to access. If you did a disk read, it would read one sector of disk. Uh if you stored 769 bytes, uh it would take up two whole sectors on the disk. Extremely wasteful. So that's why we had to really be careful about how we laid out the data. Um and and and uh uh otherwise we would we would consume vast amounts of wasted space.

Wolf:

Um and that's kind of how it's kids today don't even know what a bite is.

Jim:

You know, I wanted to mention that. I've uh over my years I've I've I've uh interviewed a lot of a lot of programmers uh either to come work for me or to work for my clients or whatever. And one of the questions I always ask them is uh uh tell me what a byte is. And weirdly, most of the time they can't tell me what a byte is. I I'm I'm astounded by that. How do you develop software? How can you call yourself a professional programmer if you can't tell me what a byte is? And I I don't hire those guys. Uh I just think like that's that's something you need to know. Uh forget about 32-bit and 64-bit integers and stuff.

Wolf:

If they don't know what a byte is, uh I don't I'm not a hundred percent sure I agree with you. Um there's lots of stuff I don't think a candidate needs to know. Um but I like I have different criteria. They have to be able to work with other people and learn and know where to look. But I'm not sure, for instance, I I don't think you need to know how to implement a quick sort, but you need to know where to get a quick sort.

Jim:

Okay.

Wolf:

Uh and these days maybe you don't need a byte. Uh because let's the place where you would often encounter a byte is in strings. And strings today are often Unicode. Maybe they're 16 bits at a time.

Jim:

Yeah, yeah, Unicode, UTF-8. That that just blows the door wide open when you're talking about character strings, doesn't it? A character can be uh between one and four bytes long. So now a single character, um uh, you know, if it's the letter A, that's gonna fit in in one byte.

Wolf:

Uh but if it's just go straight from the eighth character to the eighth byte. It just doesn't work that way anymore. Right. So my my and do I care if a programmer knows what a byte is? I mean I kinda do because it's so fundamental. Maybe you don't actually use it anymore. Um, but it's the same as knowing who Rembrandt is. Um you are not gonna paint like Rembrandt, you're not gonna deal with any Rembrandt paintings, but you really ought to know who he is. Um maybe you're not gonna use a byte. I don't know. I don't know.

Jim:

It it feels like fundamentals to me. It feels like fundamentals to me. And I think you ought to know the difference between an int and a float. I I think uh you you should be thinking about uh uh an integer being 32 bits versus a double being 64 bits. If you're working on a program, uh especially if you're in a in a strictly typed language like C, um if you're trying to store a number in an int, you need to know what the limitations of that int are. What can you fit into 32 bits? Right? Maybe in this case, I have a much bigger number. Uh you know, I've got this uh uh you know uh 18-digit number. You gotta think of how how big of a uh uh uh store, how much storage do you need to allocate for that? What data type do you need to use for that?

Wolf:

Yeah, easy in Python, hard in C.

Jim:

Yeah. Yeah. Um anyway. Uh I I wanted to mention briefly there are types in uh well, there's certainly types in languages. We talked a lot about uh the C language. Um there are types in databases. I use Postgres. Um it's it's like MySQL, it's like SQL Server, it's like Oracle. There are data types in in a database. Uh Postgres has text, varkar, car, uh they have integers, 32 bits, they got small int, that's 16, they got big int, that's 64. Sounds an awful lot like uh short int and and uh long to me. Uh they got a Boolean data type, they got decimal and numeric. Um, this is a good chance for me to talk. Uh, you know, if you're doing floating point, if you're let's say you're writing in C, and I've seen people do this. When you deal with money, I'm talking about writing a program that handles currency. People are tempted to say, well, you know, it's got a decimal point, so it should be a float. Oh boy, are you in a world of hurt if you start doing that? Uh float is uh is interesting, it's not exact. Uh it can be very, very, very, very accurate, very close, but it's not exact. Um if you uh you know for instance, you you take um you take a uh uh in a value, a dollar value, say$100, and you wanna um you want to multiply it by 6%. So you multiply it by 0.06, right? Because you want to get the tax on it. Um 0.06, that's a floating point number, right? It's a decimal number. You multiply that by 100, you don't get$6. You might get 6.000000001. You might get uh uh 5.999998, you might get something like that. It's not six. Uh people run into trouble all the time with that. You end up with rounding errors, you end up with all kinds of goofy things. So uh when you're dealing with um dollars or currency of any kind, whether it's euros or dollars or yen or whatever, you don't want to store it in a floating point number. Uh what I've always done is I I convert that number to cents. I I uh you know, if I have a hundred dollars, well that's uh uh ten thousand cents. Right? Uh if if I want to uh if I want to represent six percent, um uh well what do I do? I gotta I gotta do the math there, but you want to multiply, you know, it's six, you multiply that by your your ten thousand, uh, and you get a number, and then you might have to divide that to get the the percent. You have to divide it by a hundred to get your percent. Um you have to you gotta be thinking in terms of data types to know that what you're trying to represent will actually fit in that data type. And again, floats are not a place, floats and doubles are not a place to be storing money.

Wolf:

See, you're making me think about Rust again because uh Rust has uh uh these things called Rust knows that certain data types support certain operations. Okay. And one thing that uh your the typical language you use doesn't know. But as a programmer, you do know is that you can't compare two floats. That that doesn't give you the right answer. You have to see if two floats are close enough together. That's what you call equal. For instance, Rust has the notion that some types support the properties of uh equality. You can tell if they're equal or not. You can test that. And you can also tell if they're orderable, a couple other things. And integers you can compare for equality. They have this type, this trait. And floats don't. If you try to use equal equal with floats, the compiler will tell you you're not allowed to.

Jim:

So that fails at compile time. That's pretty cool. C won't do that. C will let you compare two floats. Uh and it'll work just fine. Well, it'll compile just fine. It may not give you the answer you're expecting uh at runtime, which you know if you can catch it at compile time, you're you're ahead of the game, right? Um there's lots of other types in databases. Uh Postgres even has types for JSON data and binary data and UUIDs and uh uh internet addresses and all kinds of stuff. It's it's pretty cool. Um uh but let's let's um let's it's enough talking about just the CPU. Let's talk about languages for a minute because there are strictly typed languages, those are languages like Rust was uh uh Wolf was talking about Rust, that's a strictly typed language. C, C, those are strictly typed. Uh uh and really to me the the thing that uh makes me think that it's strictly type is if I have to declare the variable before I use it, and I've had to say what it is. You know, a lot of languages, the dynamic languages, you don't have to do that. But in C and C and C sharp and Rust and Swift and lots of other languages, you have to say up front what that variable type is, and then you better make sure that's what you put in it. Um so uh strictly typed languages, I named a bunch of them, but also you get like TypeScript that takes JavaScript and sort of puts a type system around it, and the then the compiler for that enforces uh your types. SQL is definitely a typed language. You uh you know, you can't compare an int and a string. Um the the the the SQL uh uh engine will catch that and and uh tell you you can't do that. Uh Fortran, Cobalt, those are all strictly typed languages. You have to declare the variable before you use it, you've got to say what it is. Um the benefits of a strictly typed language are um uh the compiler will stop you from doing something you're not supposed to do with that data type. If you're trying to put the wrong type of data into a variable that isn't declared to hold that type, it's gonna tell you. Uh it might be a warning, it might be a hard error, but it's gonna tell you.

Wolf:

The the way I look at it is um there's strictly and dynamically typed languages, and it's kind of a loose uh division between the two. Both of those languages, both of those kinds of languages have types. Um both of them obey all the rules of the CPU. Uh there they are gonna have integers in them somewhere, somehow. Maybe you don't see them, it depends on what it is. But when it does have an integer that is a four-byte integer, it's gonna obey alignment, it's gonna obey packing. Whether it's strict or dynamic, it doesn't matter, that's going to be true. Uh the the way you can tell a language is strictly typed or dynamically typed, is that in a strictly typed language, you make a specific name correspond to a specific type. So when you say account balance, right at the place where you make up the name account balance, you say, and it's going to be a long, or whatever your language makes you say, to say that this is going to be a 32-bit or a 64-bit value. And from then on, in a strictly typed language, um two sides of that type come into play. One, the CPU side, that name is always going to refer to a specific shape in memory, a 64-bit long shape. And on the human side, you've made a promise that you will only use that name with values of a compatible type. You're only going to use it with integers, almost always with 64-bit integers, uh, or whatever you know, size you made. Uh but some languages also let you use that name in a way where things get converted to 64 bits or whatever it is. So that's what it is in a strictly typed language. In a dynamic language, usually you just make up a name, and that name can essentially be bound to point to. It's not necessarily like that name is a pointer. Uh it might be, but the the thing to know is that that name is referring at any moment to something. It might be referring to an integer, it might be referring to a string, it might be referring to some complicated thing that you had to make up yourself. Uh it's dynamic because you can then make it point to something totally different. It was pointing to an integer, and now it's pointing to a string. That's dynamic. You're not making any promises. Um, the compiler isn't going to stop you from doing uh a whole bunch of things that these strictly typed languages are going to stop you from doing, but it's still pointing to an object with a specific shape. There are still types. They're in there. The value that you have is some type. And in a lot of these languages, you can ask. There might be a type function or operator. So if your name is pointing at an int and you say type of that name, it's going to return int. Uh because that's what it is at that moment. But there's no promises. I didn't mean to interrupt you for that long. Go ahead.

Jim:

Um That's uh that that's we were gonna get to that. I'm glad you did. Uh that's pretty good. Um so let's talk about dynamic languages a little bit. Uh uh, you know, there's a bunch of them. Perl, Python, PHP. Those are all dynamic languages. You don't have to declare a variable before you use it. Uh uh like with Perl, you can say uh use strict. That means you have to every every variable has to be named uh ahead of using it. Uh that way it catches uh uh uh typos. Right? Um JavaScript doesn't have that. You can just you can just refer to a variable uh whether it exists or not. And sometimes it'll catch it, sometimes it won't. Uh Python, do you clear declare uh variables at all in Python? Do you have to say I'm gonna I'm gonna give this this uh piece of data a name?

Wolf:

Uh variables in Python exist because you assigned into them. If you later use a name that doesn't that was a typo, um there is a kind of error you will get, but it's not like it's a compile time error. Uh what happens is at runtime uh you use it and it says hasn't been assigned a value yet. Um but it is assignment that brings a name into existence in a Python program.

Jim:

Sure. Well you know in Perl we can say use strict, and if you're if you're a Perl programmer, I strongly advise you always include use strict at the top of your programs. That means you have to have assigned something to a variable before you can use it. Um and in fact, it doesn't really mean you have to assign something to it, you have to declare that it's got that there is the variable of this name. And then anywhere in your program you can refer to that. It may or may not have a value. If it doesn't have a value, you'll get a runtime error if you try to read from it. Um but uh if you don't use strict, um you can you you can just make up all kinds of names and typos don't get caught until runtime, and it's really, really a pain. Um uh JavaScript, uh JavaScript's got all kinds of weird things, you know. Like in JavaScript, you can say var and then give it a the name of a variable, you can say let and give it the name of a variable, you can say const and give it the name of a variable, but you don't have to. That's kind of weird about JavaScript. You can just uh later on refer to a variable and a it's it's it's a little bit weird. Um Ruby, Go, Lisp, those are all dynamically uh typed languages. Um you don't declare what the type of a variable is. Uh internally, as Wolf pointed out, it knows at any given moment, it knows that this thing is is referring to an int. Uh it has to, otherwise the CPU wouldn't know what to do with it, or the compiler wouldn't be able to write the instructions to tell the CPU what to do with it. Um there are some benefits of a dynamic language. Um what we've said already makes it sound like dynamic languages are really bad, but there are some benefits. Uh, first of all, it's uh I think in Wolf's words, it's all loosey-goosey. If you're just right trying to write a quick program, you know exactly what you're doing, you can do that. You can you can without having to declare variables ahead of time, you can just write this little program that does the thing. And that's kind of neat. And uh duct typing. What you you've mentioned duct typing to me before. What is that, Wolf?

Wolf:

So the exact origin of the phrase is that if it walks like a duck and quacks like a duck, it's a duck. Um in Python, it's duct typing. Uh if something uh supports the operations that you apply to it, like let's say in your program you've you've got a couple of names and you uh stick them together with a plus sign. If those types that they are right at that moment support plus, then that's gonna work. Um and that's kind of a use of duct typing. Uh the fact that they both support plus uh lets you lets you use plus. The the use of types in a program um on the human side, when you so this is especially true in strictly typed languages, when you say this name is this type, that's a little bit for the compiler, but most of what that's for is for you, the programmer, the human being, and for the people who go to read that program. When you say this is an int, you're not saying to the compiler, and you're always going to store it that way. The compiler could have figured that out by itself. Uh, what you've really done, the most important thing that you've done, is you've made a promise about how you're going to use that thing. And the language that you're implementing in can check whether you keep your promises. And it can refuse to compile when you don't. Uh and any place where you don't keep your promise, uh that's almost certainly a mistake. It's an error, a programming error that you made, that you want to get caught as early as possible. Um and so that's the great thing about strictly typed languages, um, and the opposite of that, where you don't make any promises, um that's the programming equivalent of move fast and break things. You can um a good Python programmer uh and a good C programmer in Python you're making less promises, you can use fewer words, it could very well be that you can more quickly implement the same level of functionality that a C programmer could. They would need more words to say the same thing that you said, and it might take them longer. Now the C programmer can do something you can't. The C programmer can find more mistakes before actually running the program, and the C programmer can write a bigger program uh with a better likelihood of running the first time than a Python programmer uh writing a program of the same size. So it's the existence of these promises that help you find mistakes and big build bigger implementations. Uh both languages are good when you're applying them to the right problem uh with the right constraints. Uh the it's the problems you're solving and the the skills of your team that help you pick the language that's right for that situation. Uh both are good. I happen to love Python, I happen to love C.

Jim:

Yeah, I uh there are there are places to use both. Um it it depends on what you're trying to do. And and uh I've written an awful lot of Perl code and it's it's a dynamic language, and uh I I I couldn't have moved that quickly, uh I think in a strictly typed language. Um but as as a project manager, um a strictly typed language, like you said, would catch the error, the compiler would catch the error. I'd much rather catch the error at compile time than at runtime, because I'm not in in my code, I'm not always gonna run every branch of execution myself, but my users have a way of running things, uh, and I hate it when they catch the air. I want my compiler to do everything it can for me. Uh that's why I turn on use strict, at least with with Pearl. Um yeah, so I I was uh as we were preparing for this episode, uh I was talking to a friend of mine. Uh yes, Wolf, I have other friends besides you. Uh at least one. Um and he was asking, um, if you store uh a number in a in a dynamic language, let's let's pick Pearl, for instance, if you store uh the value 10 in a variable, um and uh internally it's probably gonna assign a uh 32-bit integer, if that's the the machine architecture, right? Uh it's gonna assign that uh a 32-bit integer to store it. Um and then you add a much larger number to it. How does the language deal with that? Does it uh under the, you know, let's say I've got the value 10, and I add uh uh uh six trillion to it. What happened? Do I overflow? What what happens in general?

Wolf:

In Perl, I don't know, because I don't I don't know much about Perl. In Python, I actually happen to know this exact problem. Uh and Python has the thing the thing that it shows human beings is that there's a type called number. Um and it turns out that the size of the number you're trying to work with controls what the actual underlying inside the computer implementation of that number is. If you're using a very small number, something less than 254, um not only is that number stored in the smallest, but you need an object. If if it if you want the number 200, the number 200, but you want that thing to be an object in Python, there is an object for 200 and it's a singleton. There's only one. Every 200 that you have in your program is that same object. If what you have is bigger than 254, uh but small enough to fit in 32 bits, um, then it's probably a very small Python object, not much bigger than a wrapper around the 32-bit value. And no matter whether that's the same as some other uh number somewhere else in the program, they are each their own object. Um and if your number gets really big, bigger than a 32-bit value or or whatever the limit is, um, it gets represented by a special growing uh data structure that can represent uh almost any sized uh number, integer anyway, uh limited only by the amount of memory you have. And the single name that you have pointing to this number, um, no matter what you do to that number, the underlying thing that name points to will fluidly switch back and forth to the appropriate implementation without telling you anything, without changing the name, without revealing what it is uh from you using uh whatever type of or type operator the language gives you. It just is going to do the right thing. Now that doesn't mean you can't tell what that thing is. Uh Python is kind of a glue language in a lot of ways, and it has a special relationship with, for instance, C. It has a C API boundary that you can get to. Uh in C, you can write C code that sees one of these Python objects and can look at the object and tell which one of those things I just said it is. But on the Python side, you don't know. So that's how Python does it. Uh I'm sure what Perl does is plenty sophisticated. Uh I just don't know what it is.

Jim:

Okay, so yeah, it it morphs that little variable to it it bends it to be whatever it needs to be. Right. Um let's get on to uh we talked a lot about the types that are built into the to the uh the to the to the language, uh if it's a strictly typed language. Uh but there's also something called user defined types. You can define your own types. That's kind of neat. If you're in C, you can do something called a type def, which lets you basically uh name your type. You could easily say typed uh I I forget the order of this X, but but like uh typed uh uh uh typedef uh int um my int. And it lets you create a variable uh a data type called my int. Right? That's not very important when you're just dealing with these simple little data types. That becomes much more important when you're dealing with something else that we want to talk about and that is structs uh uh structures in C. It's it's a struct uh and that's a um an aggregation of types is that is that what you'd say yeah I'd call that an aggregate type you used exactly the right word yeah an aggregate type uh so you might declare uh uh in C you might declare something called a coordinate which would have uh at least two two variables an X and a Y and a three-dimensional thing it might have th a Z. So you create something called a coordinate you use a type def to give that a name uh now you can declare a variable of that new type so so you you you uh create a structure and you use type def and you give it a name of uh chord C O O R D that's common right uh and then uh and then you uh because you use type def to give it that name anywhere on your program now you can declare a chord uh you can declare a variable of type chord um and that variable's got two or three pieces to it and that's what a struct is uh and here's something I I learned just like last week uh I've done a lot of structs in C. I did a little bit in C and uh and then I hadn't used them for years and years and then I did a lot of Swift programming and Swift has structs and something that really surprised me is Swift structs let you have methods on them. I thought wow that's really cool. Well Wolf told me C has always had that I just never realized it I always thought classes had methods and structs had just an aggregation of fields. But no uh uh structs can have uh methods attached to them as part of the definition.

Wolf:

And in fact the thing that I told you is that the in C, the only difference between structs and classes is the default visibility of the uh members. Uh in a struct the default is everything is public and in a class the default is uh everything is uh I think everything is private unless you say otherwise and you usually do.

Jim:

So it makes me wonder why wh why are there two then why do they have structs and classes? And I suppose one of the reasons is structs came from C, C didn't have classes, structs uh the the members were public, so maybe uh C is still that way because a lot of people moved from C to C and it's kind of compatible.

Wolf:

In fact the original name of C was quote C with classes unquote.

Jim:

Yeah. Okay. So so maybe that's why we still have two of them. It seems like you could do the same thing with one and it might be safer if by default everything were private and you had to declare it public in order to access it. But that's uh that's where we're at, right? And then there's uh another thing you can use and that's a union. Unions are kind of neat because that's basically saying two different types of things can occupy the same bit of memory. Right?

Wolf:

Is that how you'd say it uh I would I would what you said sounds great except I would have added but not at the same time or certainly not at the same time.

Jim:

Back in days yeah back in my COBOL days we we took advantage of something like this all the time. I think it was called uh uh redefines you would declare a record layout and then below that you'd declare another record layout and you'd say it redefines the first record layout. So now you've got two record layouts pointing to the same bit of memory that uh are totally different layouts. Um and boy you can get yourself in trouble when you do that kind of thing.

Wolf:

It's kind of a way to do what C and C call uh cast C casts C only has one way to cast. Maybe I don't know what C99 has. C has a bunch of different kinds of casts. The one that this would be like a union or a uh re-declare that's called a uh reinterpret cast you grab out something inside a value uh by one type but you had already put it in with some other type so it's just like you changed types maybe what you got isn't sensible but but that's what you did.

Jim:

Yeah it's it it's uh it's interesting you can get yourself in trouble uh but it can be useful sometimes um uh enums um you know the enums exist in C and I used them a little bit and I think an enum uh uh uh in c was just an integer right that could have a a defined set of values that's what I'm remembering um uh but enums exist in in Swift and I think they do in Rust as well.

Wolf:

They do and uh in Swift and Rust they are not at all like what they are in C. In Swift and Rust they rock.

Jim:

Yeah they're pretty similar I think uh I've done the Swift stuff you've done the Rust stuff and I think what we've talked about they're they're quite similar um they're they're they're just pretty cool you can store strings in them and and all kinds of things in them and then do funny uh iterations on them like each different name that is a possibility in an enum can be its own totally different type.

Wolf:

And when you have an object that is an instance of this enum um it's discriminated. It knows which of those things it is uh like it for instance uh in r in uh Rust there's a thing called uh a result and a result is an enum that's uh specific to some particular type like you might have a result that is a point um and that result uh is either um okay and the value is that point uh or it's error uh error I think is what the actual name is inside the the enum and the value of that name inside the enum is an error of some kind uh and there's also a thing called option uh and the two names are sum and none uh none is that has no value at all it's just that name and sum has the value of uh like we we were just saying yet a point uh sum the value is that point um so if you had a point to return you return a sum SOME sum some point uh and if there was no point answer it just didn't have one uh then you return none uh and if you had an error i you would return uh an error uh so either you're gonna return an option or you're gonna return a result um I mean I guess you could return a result that is an option if it's okay to return none um uh and that there's a possibility of an error in some other way uh but those are two you could return one the other or some combination of them uh error is a name inside result and none is a name inside option um so if you're returning an option none's a possibility if you're returning a result error is a possibility okay if you're returning a result where the thing that it is uh a uh a result of is an option then you could return you could return okay some point or okay none okay or error something I I I I sort of remember early on when you first started looking into Rust you were uh surprised that it didn't have exceptions and I think as you learned surprised and disappointed to surprise and disappointed but as you learned you sort of learned the power of this thing that you return and I think Enum was part of your description of that and uh and then you started to realize that's not so bad.

Jim:

Not having an exception.

Wolf:

Not only is it not so bad the Rust way uh once you understand it uh felt superior to me. Like I I once I understood I I liked the Rust way better. That's pretty neat how you sort of had a flip in your thoughts about that just uh as you started to understand the language and and the way it returns uh the way it returns things including errors um uh let's talk about references for just a second here uh this this episode is running much longer than I expected it to uh but I think you wanted to talk a little bit about references sure um so the CPU knows about pointers uh it doesn't know a whole lot about pointers um it's the exact arrangement of the instructions that go to the CPU that let the CPU understand what a pointer points to but the CPU knows that there's a thing called a pointer or uh in inside the CPU we usually say address and there's a lot of instructions that follow addresses and get someplace. A reference is uh a feature of a language and a reference is typically exactly like a pointer but in always hidden from the programmer. So in C, for instance, or C, um if you have a pointer named X, and it points to an int, you can say star X and that is an int. If you just say X, X is a pointer. Star X is the int. So star D references the pointer. That's exactly right. If y and you could make X point to some other int. If you said X equals and then gave it a different pointer, X is now referring to a different int. If you have a reference if X is instead of being a pointer to an int, a reference to an int, then when you say X it's implemented as a pointer but you don't have to dereference X. When you say X in your program it looks like and acts like an int. That dereference happens automatically so that's one difference from a pointer. The other is when you have a reference you can't point it at a different int somewhere else in memory. You can't rebind it. Yes, you can change the int uh that's at the space it's referencing at the place it's pointing to it was pointing at the value three you can make that three become a four but the three is gone now. The place in memory that had a three in it now has a four. If it was a pointer you could be pointing at a three somewhere in memory and you could make it point someplace else in memory where there was a four and that three would still exist and maybe other things would be pointing to it.

Jim:

Sure.

Wolf:

That's a difference. And it's a really crucial difference because of um these promises, these APIs um how you call things how things pass through functions a thing we didn't discuss that is very important to types but only with respect to how they pass through functions. You've got some and you're going to call a function and you want to tell the function those things a ver th something that you pass into a function inside a function those values can be passed by value or pass by reference. For most small things you will pass by value. If you had a character the thing you send into the function is a character a copy of what you had before. And if inside the function that character gets changed that's not visible outside. It got a copy it changes the copy nobody outside the function sees that if you passed in a pointer um or reference. Well well let me start with pointers that pointer is copied. If inside the function the pointer name that it got gets pointed at something else that's never seen outside the function. But if you changed the thing that pointer is pointing at, if you destroyed the three and put a four there, the caller will see that. That's a way to pass back uh values to the caller. It's not a way people like usually they want you to return a value. And there's also pass by reference. If instead of copying in a pointer you passed a reference then you could inside that function change what the reference was the value that reference referred to and that is just like destroying the 3 and sticking in a 4. The caller will see that. In C, and maybe in C99, I I don't know enough about C99, you can say it is a const reference that the thing it points to can't be changed. In old style C, if something was the right size, it automatically was passed by value. Characters and ints were automatically passed by value. And if it was a struct or something it was I think automatically passed by reference. In more modern languages and I think C99 is one of those uh but certainly in C and Rust you get to say I'm gonna pass this by reference or pass by value and even a very large object might end up getting copied sometimes not even by the compiler sometimes according to the functions methods that you've supplied to that big aggregate type that you've made. For instance C has a type called string and you can say whether a string is passed by value or reference. A string might get copied. Maybe that's not what you want. Maybe you wanted to pass it by const reference so that you got the original string but you weren't able to do anything to it. This is all in the end yeah it's machinery about how types and objects get moved around but in the end it's all about promises. It's all about uh and the special word we make for promises when we design them with these strictly type languages APIs um which are application uh programming interfaces um that's what helps us make especially libraries act sensible they have a model and they're designed to work like you would guess that model works uh so you don't have to know all the promises up front they're sensible promises if the library's designed right and that's a thing that lets you build bigger programs because you don't have to look inside the libraries to know that they obey their promises. Um and that's what I wanted to say about that.

Jim:

Yeah thank you um we've gone on a long time I we've just got a few more things we want to cover uh we we talked extensively about uh passing by value passing by reference uh and that's pretty neat uh and let's talk just a second about casting um and that's what you do to turn one type into another sometimes casting is going to be something really simple like turning a uh uh uh a short int into a long int right that happens automatically for you and see if you try to assign uh uh the value of a short into a long it'll extend that value to fit it'll take your 16 bits and and expand it out to 64 bits that just happens automatically for you if you go the other direction like you won't lose any data that way if you go the other direction if you try to take a 64 bit int and fit it into a 16 bit int you're likely going to lose some data right in C. In C, yeah. Uh and and that's why I I think it's important to understand what data types you're working with and what happens.

Wolf:

You know if you have a big long number that's uh let's say uh uh one and a half million the value is uh one and a half million and you try to c uh uh move that into a a short you're in trouble you're you're not gonna fit and the compiler and in some languages for you in some languages uh there's casts that can do the appropriate thing um there's uh casts that can cause uh the assignment to happen but be checked at runtime that's one kind of cast and there's uh the compiler might understand what values are there so you could tell at compile time that the thing you're doing is wrong and to ask for that specific uh kind of check there's a sp special cast for that in whatever language you're using. Uh C has maybe four or five, maybe even more casts than that. Some of which are easy and some of which are hard, uh some of which cost you money at runtime and some of not money. Well money, yeah. But cost you calculations at runtime and some which only happen at at compile time. Uh so casts are very important in this way. Uh helping you catch errors and where you are charged for the performance of a cast, that's a thing.

Jim:

Thank you. Um I I I think uh I I think we've probably talked enough about types, don't you think? That's uh took a lot longer than I thought. Uh we do have a few takeaways though. Um you want me to do them? Yeah, yeah. You you go ahead.

Wolf:

I think uh the things we want to say types about types are pretty simple. Uh there's the side of types uh that the CPU knows about. Let's call those types atomic types. Uh they're the ones that are built into the instructions, and the CPU knows what you're talking about uh by the instructions you're using. That's one side. Um and then there's the languages uh that you use. Those go those have types beyond what the CPU knows. Uh they are types built into the language, um, but there's not specific operations at the CPU level. Um but there often are in those languages. Um shoot, I'm suddenly blank about what kind of uh languages and types those those might be. Um but uh an example certainly is Boolean. There's lots of Boolean operations um and what numbers can be convert, what things can be converted back and forth from Booleans, and languages often know about those things, whereas uh CPUs only really know about integers, for instance. Uh in strictly typed languages, when you use a type, it's not just uh saying how you want it to be stored. You're making promises about how you will use it, and the strictly typed language can check that you obey those promises. And it's those checks at compile time that help you write more consistent and often bigger, if they need to be bigger, programs more safely. Uh and in dynamic languages, it's because you don't make those promises uh that you can sometimes move more quickly. And I think finally, the last takeaway is uh that types are building blocks, and when you want to model something much more complicated than an integer, uh and I'm gonna just use the example of a bank account, uh, where you have lists of deposits and withdrawals, and maybe you have multiple actual piles of money. Um that's an aggregate type that might have methods of its own, it might be stored its own way, it might be passed in and out of functions in specific ways. Um these user-defined types are how you make bigger promises. Um and in the languages that are good at that, um, they're how you build the language that you're actually going to use to solve your problem. Because Python doesn't solve your problem, C doesn't solve your problem, Postgres doesn't solve your problem. None of these things by themselves do. It's you modeling the problem with these bigger types and building the language that's specific to these objects and types that let you have a tool that's really good at solving those problems. I think that's the set of takeaways.

Jim:

I I I I think the the the real takeaway for me is based on what you just said, that the the the one to remember is promises, right? Uh when you're dealing with types, you're making a promise to the to the machine uh what this is gonna what what kind of value this thing is gonna hold, and you're making a promise to the programmer that this is uh a bank account, or this is a transaction uh that goes against a bank account. Promises. Uh that that that's kind of like the word that that sums it up, I think. Um I I before we finish, uh I want to comment about a little cartoon that uh uh Wolf passed this to me maybe yesterday or the day before. It's a cart uh it's a uh it's a little cartoon thing. Um and the uh you know we're an audio-only podcast. I can't show you what this cartoon is, but I can describe it. It's quick. Uh it's SpongeBob. Uh in the first one panel is uh uh he says, uh Rust, when I have an atom of difference between my type and the expected type. And Spongebob has got this frustrated look on his face. And then the next one is uh Python, when I cast a float into an unsigned Toyota Yaris 2023. Uh and SpongeBob's got a big smile on his face uh because he's happy. Uh that kind of sums up, I think, what we've talked about. Uh between strictly typed languages like Rust and dynamically typed languages uh like like uh Python and Pearl. You can do all kinds of crazy things. Um anyway, that's that's our takeaways. Um so much for listening. Yeah, take us out, Wolf.

Wolf:

Uh exactly what Jim just said. Uh we appreciate listening, especially if you got all the way to here in such a long episode. Uh there are show notes wherever you got your podcast. The show notes ought to be attached there. We have a website, runtimearguments.fm. We want your feedback. Uh feedback means so much to us. It guides us, it corrects us, it gives us something to tell you uh and more things to think about. Uh we already told you, I'm gonna tell you again. Feedback at runtimearguments.fm. Uh thanks so much, and uh we'll see you later.

Jim:

Jim? Thanks. Thanks, Wolf. Thanks, listeners. Uh, I appreciate you guys listening, and we've had a lot of fun with this episode. So thank you, and um looking forward to the next one. All right, bye bye.

Podcasts we love

Check out these other fine podcasts recommended by us, not an algorithm.

CoRecursive: Coding Stories Artwork

CoRecursive: Coding Stories

Adam Gordon Bell - Software Developer
Two's Complement Artwork

Two's Complement

Ben Rady and Matt Godbolt
Accidental Tech Podcast Artwork

Accidental Tech Podcast

Marco Arment, Casey Liss, John Siracusa
Python Bytes Artwork

Python Bytes

Michael Kennedy and Brian Okken
Talk Python To Me Artwork

Talk Python To Me

Michael Kennedy