Programming Throwdown - Functional Programming

Episode Date: June 19, 2019

Hey all! Since episode 82, we received a ton of email asking for more info on functional programming (FP). To cover FP in great detail we are thrilled to chat with Adam Bell. Adam is the host... of the Corecursive podcast and an engineer with many years of experience in FP. In this episode, we dive into what FP is all about, when it's useful, static/dynamic typing (our favorite topic), and other areas of FP. Thanks again for all of your emails and support. It is a treasure to hear your inspirational stories and we are so greatful to be creating content for over eight years. Happy hacking! Show notes: https://www.programmingthrowdown.com/2019/06/episode-91-functional-programming-with.html ★ Support this podcast on Patreon ★

Transcript
Discussion (0)
Starting point is 00:00:00 programming throwdown episode 91 functional programming part two take it away jason hey everyone so we we uh got a lot of feedback on our interview with Jonas Bonaire a few months back. And a lot of you really wanted to know more about functional programming and really dive deep. And I'm really excited that we have Adam Bell, engineering manager and podcaster. He's been an engineer for about 15 years. He's done a lot of functional programming in his career. And yeah, we're going to sit down and have a chat about functional programming, about Scala, about a lot of these different concepts. And really kind of dive deep, start from the basics, and get people kind of ramped up onto functional programming.
Starting point is 00:01:00 So welcome to the show, Adam. Yeah, I'm glad to be here. Cool, cool. Yeah, so what is functional programming? So at its simplest level, it just means that you would construct programs only using pure functions. And a pure function would be something that, like a function in the mathematical sense. So it takes in inputs and it produces outputs and nothing else. So that means, you know, no modifying of global state, no, you know, modifying data structures in place, no throwing exceptions. And maybe the more tricky requirement is like no reading of user input, no writing of things into the outside world.
Starting point is 00:01:47 So that is kind of a high level of what pure functional programming is. Yeah, yeah, that makes sense. I think one of the things that I always found really tricky was exactly what you said. I mean, at the end of the day, a program is going to interact with its environment. That could be reading from a file, that could be writing to the network buffer or something like that. And I found that to be one of the hardest things to grasp when you join it with functional programming. So it's sort of like, how do you, you know, a file is kind of inherently stateful and it seems very natural to have this global file because you only have one of these files on your hard drive, right?
Starting point is 00:02:26 And how do you get people from thinking in that way where they just have all of these globals for all of these environmental things that are literally global? How do you get them from that mindset to this functional mindset? Yeah, I mean, I think you can think of it as a design constraint that you place upon yourself. So I think a common pattern you might see is having a very functional core of your program, and then kind of an imperative shell around it. So if you're, if you have the file, as you're saying, and you need to do a lot of transformations on it, you know, you may have, like, functions that are ostensibly pure that take in, you know, lines of that file and do some sort of transformation. So they meet the definition. But somewhere at the outside, you have some imperative layer that, you know, does the actual IO. And I think that it's a really
Starting point is 00:03:21 useful design constraint, because what you end up up with if you limit that imperative side effect D stateful code to the edges is a system that's very testable. Like all the parts except that imperative stuff can be tested quite easily. They just have, you know, for this defined output, do I get this? For this defined input, do I get this defined output? And so testing is easy. Reasoning can be a lot easier in that world where you're kind of pushing towards functions. So I think that it's a challenge, but it's certainly one that has a lot of value in my opinion. Yeah, that's actually a really good way of looking at it. You know,
Starting point is 00:04:11 I think when I started working in industry, you know, through my, if you can actually go and look at my PhD code, it's, I'm not proud of it at all, but, you know, it didn't really have any tests or anything like that because you're just kind of writing it by yourself and so one of the real challenges when i got into um you know more of an industry role was was uh kind of realizing that oh we have to really write tests because we're really depending there's other people who are sort of depending on our code to behave in a certain way we can't really use a lot of our own intuitions and spread those through osmosis to the rest of the team. And sometimes you find that after you've written something,
Starting point is 00:04:51 you go to test it and you realize it's impossible. It can't be tested. The only thing you could do is just test main, right? Yeah. And then you say, oh, well, I have to modularize this. I have to break this down. And while you're doing that, you say, oh, well, I have to modularize this. I have to break this down. And while you're doing that, you say, okay, I'm going to pull this function out and test it in isolation. But to do that, it needs to be context-free, right? If you go to test that file,
Starting point is 00:05:17 that function, and it calls a global and crashes, you say, oh, okay, now I need to take that global and pass it into the function so that I could pass in a dummy or something, a dummy object. And what you're doing is basically you're learning functional programming. So I think, yeah, a good way to get started, if you've been going through some tutorials, you're learning how to program and you feel pretty proficient at procedural language, maybe C, C++, Java, I think testing your code, even if, you know,
Starting point is 00:05:47 you might be the only person who will ever use it, testing it will be a really good exercise in software architecture. And along the way, you'll be forced to discover functional programming in one way, shape, or form. Yeah, no, I totally agree. And I think that it's been thrown at me before, like this statement. Hey, this, if your code isn't easy to test, then it's not good code. So I've, you know, people, especially like people who are really keen on test driven development will say this, but the problem I have with this statement is like, it doesn't really tell you what to do, right? It's just like, hey, this code is bad. So I think that some of these functional principles can guide you in that direction to say, no, I mean, you can even have things that are well-tested that just aren't good code because you have crazy mocks and stub services and whatever. It's all pound defines, compiler macros. Yeah, exactly. So, I mean, to think about things as being pure functions as much as you can, I think really guides you in the right direction. Yeah. Yeah, that totally makes sense. So what are the functional programming languages that you use the most? So I spend my time in my day job writing Scala, which is kind
Starting point is 00:07:08 of, I guess, a multi-paradigm language. It supports like, you know, Java style object-oriented stuff, as well as functional programming. And so that's where I spend most of my time. Huge fan of the language. And then, you know, I am guilty of of playing with a lot of other languages so i spent time teaching myself haskell and um that was certainly a great experience and yeah yeah we had we had a lot of haskell at a place i used to work and um it's it's it's interesting i actually really enjoyed it. But part of the challenge was we were building a software library
Starting point is 00:07:50 for other people to use at the company. And so what that meant is anyone who wanted to use this library had to learn Haskell. We found that to be really difficult. And so we ended up having to rewrite the whole thing in Python, which is pretty sad because it looked pretty elegant in Haskell.
Starting point is 00:08:08 But this is just the way of the world. Yeah, I think that Scala, because it is multi-paradigm, it can be used as sort of a better Java. And so that maybe makes it more palatable. And also, if you were building a library, in your specific case, there's nothing saying you couldn't use that from any other JVM language. So there's some benefits there.
Starting point is 00:08:38 I mean, the trade-offs are, Haskell is a very hard line. This is a pure functional programming language there's no or very few like escape hatches i guess um whereas you know if you're trying to apply an fb style in a language that doesn't enforce it um i think that requires you know like obviously if the language isn't enforcing it then that's kind of up to the team to say this is a goal you know yeah exactly i think if you're building a service you can get away with it because you can write a protocol and um and yeah you know but if you're
Starting point is 00:09:10 building a library then yeah i mean the lesson i learned from that experience is is or really i guess i wasn't the tech lead at the time but the lesson the tech lead learned is to really know their audience um i think that part that that's kind of a universal truism So you said you're doing Scala I've seen Scala applied in many different ways So it's used in Spark Which is this big data compute platform There's the Play framework
Starting point is 00:09:39 Which is kind of a web service Are you using any of those? What's sort of the scaffolding you Are you using any of those or what are you, what's sort of the scaffolding you're using on top of Scala? So we have one project that is a play project, but we, I mean, it's more of our legacy product. So we're building, I guess, web services. And the main library that we're building i guess uh web services um and the you know the main library that we're using is called uh http 4s and it kind of is very much in the paradigm of of using scala to be uh
Starting point is 00:10:16 for functional programming and uh like it provides a really nice metaphor on top of of working with a web service so a like if i'm writing a code to respond to some route that returns uh like some user information um that maybe gets aggregated from somewhere um in http 4s with this kind of functional model i have a function that uh gets in a data structure that represents a http request. And then the thing I return at the end of the day is a data structure representing an HTTP response. So it kind of fits this function model, data in, data out. What about contextual things like cookies? are they in the request object um yeah i mean cookies do come in the request object and i don't think that i don't think that violates the uh like you're still getting everything and you need basically yeah that makes sense so basically so the request
Starting point is 00:11:16 is sort of this uh multiplexer or this this this structure that has cookies as headers probably has the then it also has the body with the actual if it's a post request it has the body and then you can return some response that maybe has the status code and the the body as well or something like that yeah and then you may further subdivide this right because you probably want to take some sort of structured data out of that request and return some structured data and have ways to format it. But at the high level, it's a very simple metaphor. A long time ago, I worked in ASP.NET and they had this like page lifecycle model. And I remember like, you know, I wanted to return that, you know, the status code was whatever, 409 or something,
Starting point is 00:12:06 and you write the code to return it, but in fact, behind the scenes, there's some page lifecycle, and it's already returned a response code where you are at, right? So you had to understand this like, oh, it's not just that I'm writing the things that return the body. There's this lifecycle that lives outside of my code. Oh, geez. And so that's the body. There's this life cycle that lives outside of my code. Oh, geez. And so that's very confusing. And I think, I mean, most web frameworks don't work this way
Starting point is 00:12:32 nowadays, but I think it shows how like this functional model where you kind of get in all your inputs and then get out all your outputs is much simpler than something where there's some sort of, you know, extraneous information, like in this case, that the header is sent, you know, by overloading some other method in the framework or etc. Yeah, yeah, that totally makes sense. I think, you know, a lot of people might say, well, you could do functional programming in any language. And, you know, ostensibly, that's true. I mean, you could you could fit the paradigm. It might not look that pretty. So in the case of Java, all of your functions would have to be objects that contain one method. But it's doable.
Starting point is 00:13:13 But the nice thing about a functional language is that, as you said, it might not completely restrict you, but it makes it very easy to write functional programming and it makes it more difficult to write this um sort of the procedural programming where you're or just pure um yeah pure like recipe-based programming where you have all just global variables and so it's like you can do anything almost anything in almost any language but it's really you know the it's almost like being a an artist right i mean you could paint almost anything with any paintbrush if you had the dexterity but certain paintbrushes will make it very easy for you to do certain strokes and And so like any art, certain languages and certain frameworks
Starting point is 00:14:07 will make it very easy to craft your design in a certain way. And the functional programming way is extremely powerful as long as you aren't too dependent on, as I said, a lot of these environmental things. So a web service is a great example because effectively bits come in, bits go out. And the only thing you really have to interface with from a real world standpoint is the network card. But that's going through so many layers of abstraction that functional programming is a no-brainer there i think this a lot of this big data transformation logic is also a really good candidate for functional programming which is why
Starting point is 00:14:51 you know sql and and scala now with spark and a lot of these languages are are functional because they really excel in these environments yeah and uh like with spark and and data processing i think one reason it's a really good fit is just like a you know if we talk about immutability that you're kind of um not changing the data in place but kind of uh transforming it into a new uh into a new format uh that's very like easy to split up and and and distribute across machines and stuff um yep how do you deal with things like uh databases where you know database is this is this inherently sort of mutable object yeah i mean so if you talk about like you you were talking about haskell um and haskell has like this concept of like io where they kind of wrap anything that has an effect
Starting point is 00:15:47 in this IO type. And then instead of actually performing the action, right? The action is, it's not actually run until the end of kind of the, like until you fall off the end of main, right? It's kind of building, we're building up a program that doesn't get run until the very end of main right it's kind of building we're building up a program that doesn't get run until the very end of the world um and so that is a way i don't know if that characterization makes sense but that's kind of a way to encapsulate uh making changes to the outside world while still
Starting point is 00:16:17 living in this kind of uh pure function world and so um what we do on our team is very similar. So we use like an effect type called cats IO, I believe what it's called. So methods that perform an action upon the outside world, like instead of having something that instead of having something that goes out from a web service, let me think of an example. So I call a web service and get back an integer, let's say, and then I need to use that in some further computation. So clearly, there's some sort of interacting with the outside world there.
Starting point is 00:16:55 So how we would handle that is we have this IO type. So instead of having this function that returns an integer, it returns IO integer. And this is somewhat similar to kind of like the async await pattern that you see in a lot of languages. Yeah, or a promise, I guess. Yeah, so the key thing is that it doesn't actually run until you tell it to run.
Starting point is 00:17:19 So what we end up returning is, yeah, like a promise that hasn't been started yet. And so you kind of compose these. Let's say we need to call out to a bunch of web services, like, you know, call, get an hint from this one and feed that into this one, so on and so forth. So we return these IO wrappers and we compose them together to say like,
Starting point is 00:17:41 okay, when this one's done running, feed that value into here. And it's very easy to compose. And then at the end of the world, like at the end of our request chain, we say, okay, now run this. And so that lets us kind of encapsulate the dealing with the outside world
Starting point is 00:17:58 into this type that we wrap the results in. Yeah, that makes sense. Actually, one thing you mentioned is a really good point. Functional programming, because each function is isolated, it lends itself really nicely to parallelism. For example, you might write a simple script.
Starting point is 00:18:22 Maybe you write a simple Python script that does some text transformation, and you have this huge block of text. Maybe it's some comma-separated value that you pulled out of this Excel spreadsheet you've been working on that has thousands of rows. And you're going to do
Starting point is 00:18:38 some transformation on all of the on each line. If you just do Python, you could do it. It might not take that many lines of code. You just do a for loop for each line, do your replacement, right? But it's going to go through each line one at a time, right? But there's no reason it has to do that. You could have one process loading these lines from disk and then another process writing them to disk. And both of them can be going as fast as possible.
Starting point is 00:19:12 With Python, that's going to require setting up a thread pool. It'll probably have to be a multi-processing thread pool. You have to create all of these, spawn off all of these tasks. You have to have a feature. You have to do a lot of work yourself, a lot of the heavy lifting. With a functional language, they've designed it so that they do a lot of that work for you. So for many of these languages, and now this is starting to make its way into a lot more than just functional programming languages. But yeah, this whole future promise async await pattern, that really came out of functional programming. And for example, you can write something that solves a game search,
Starting point is 00:19:58 like solves a checkers game or something like that in Lisp, and it will automatically use all of your cores. You don't have to be fuddling around with thread pools and all of that yourself. Totally. It's interesting what you're saying about how this stuff is kind of feeding out into other languages. Because if you think about, you know, at some point,
Starting point is 00:20:21 Python having map and filter and stuff was considered functional programming, just because that was an idea kind of feeding out. parametric morphism that originally came from Haskell and then was brought to Java. And, you know, like lambdas obviously are quite popular now. So I feel like there is, you know, a conveyor belt of taking these ideas and feeding them back to other languages because there is a lot of value in them. Yeah. I mean, especially, I mean, a web server is a great example where you might have one person who they, maybe they're on their phone, and they send you a request saying, hey, get me the weather. And your service tries to return the weather,
Starting point is 00:21:18 but that person goes under a tunnel, and now they have no reception. And so you're just pinging this person saying, hey, I have your weather, I have your weather, come get your weather. And if everyone else, maybe you have 100,000 users on this site, if they're all blocked because of that, your website just, it's not gonna be functional, right? I know, pun intended.
Starting point is 00:21:39 But that's where, again, a functional language is really shying because that actually can be really tricky to get right. Even if you have eight threads, now you can support eight people. If eight people lose reception, your website goes down. And if your website has thousands and thousands and thousands of people, that's not unreasonable. Functional languages are really, really good at having these executors that sort of manage a lot of this.
Starting point is 00:22:09 So if there's a function that's waiting on some hardware device or some IO, that's okay. The language, the engine underneath the language knows to just put that one on hold, pick up a different one. And that's the kind of thing that can be really, really difficult to get right. So as we talk about a lot of these concepts making their way into other languages, keep in mind that there's a lot of advanced techniques in the functional languages that still make them really, really good for much better at doing these kind of tasks. Yeah, totally. Um, there was an example I remember from, from when I was learning this, um, that, that kind of made a lot of sense to me where somebody had like this, okay, here's like a, a service that, that processes, uh, coffee,
Starting point is 00:23:01 like you're buying coffee. So it takes in, takes in um like a a credit card and then you know it returns like some you know something representing a cup of coffee and then you know in the body of this it goes out and charges your credit card it seems like a reasonable solution right and then so but obviously it doesn't kind of of meet this functional aspect we were talking about. So if you could transform it, so you take in the credit card and you return both a coffee cup and then something that kind of encapsulates this effect. So let's say it's just like a data structure that says, you know, charge this card so much money. And then somewhere, you know, obviously you have to actually have to apply this charge. But the interesting thing is if you start thinking about adapting this, now what happens if like, you know, we say you make the one solution, I make the other. And then, you know, requests come in like we want to buy, you know, a whole bunch of coffees, like we're going to buy five coffees.
Starting point is 00:24:02 In the system where we're going out and like like, charging the card for every coffee that comes in, I mean, that's not what people expect when they buy a coffee. Where the system that kind of returns these charge objects, you could imagine just a process that kind of merges them before it actually, you know, sends off the request and is able to like batch the effects, right? So this idea of making the effects, making the side effects you're going to do in the world, like an explicit thing in the domain of your software. I mean, I think that's one of the kind of ideas, if that makes any sense. Yeah, totally. I mean, I think this will also be revealed when people try to test things. So let's say you have some service that configures your router and you try to test it.
Starting point is 00:24:53 So if you have a unit test, which literally is going to go and configure your router and you're going to run it hundreds of times and people will be running it with bugs, well, you're going to have a really bad router, right? That's a scary network to be on. So what you really want is to mock that out. And by not allowing, let's say, globals, for example, or by discouraging globals, you kind of force people to say, okay, this global router object that points to some driver that i got from cisco um you know i can't i can't rely on that always being there or i can't rely on globals at all
Starting point is 00:25:32 let's say so maybe the first step is let's pass that in and well as soon as i pass it in now i could pass in something else as long as it has the same signature and that's kind of how people can, that's sort of how, I guess, well-tested or professional software works. Yeah. What about in terms of typing? So a lot of the early functional languages weren't typed. I mean, I'm thinking Lisp.
Starting point is 00:25:58 I don't think Scheme is typed. They're all weakly typed. Now Scala is strongly typed. They have all weakly typed. Now Scala is, you know, strongly typed. They have the type inference engine. Do you feel like there's, you know, what sort of side of the coin are you on? I'm definitely on the side of types. And when I think about the value that I get out of this proposition, I was saying earlier, like, you know, a function takes some inputs and gets some outputs. A lot of the value I get is that the types kind of constrain what those inputs and outputs are. So I think types are super powerful.
Starting point is 00:26:32 And, like, I think that functional programming in Scala, in Haskell, in, you know, more researchy languages, or two languages um pushing the type system to be able to better encode um the constraints of what you're doing is is like a huge win in terms of software maintenance so yeah sorry go ahead oh i just i definitely agree yeah i mean i've been burned so many times by weekly type languages that yeah i'm kind of done with that yeah and like um if you look at like scala or let's say kotlin or even rust or swift like one thing you're seeing is kind of using uh like a result type or an option type or something rather than like a null pointer um and like that so that is another idea that's kind of you know moving out into the ether of other languages from functional programming and just that thing is so so valuable right just to say like hey you're not going to get a null pointer here you have to explicitly handle like
Starting point is 00:27:36 if this is you know possible that this value is not defined that's an explicit thing you need to handle yeah i think i agree with you. It's so, so useful. There was an issue the other day I saw at work where there's basically a function that was meant to return some information and it didn't support null. And so we ended up getting a crash at some point saying that someone tried to pass in a null. And it turned out that there were some circumstances
Starting point is 00:28:05 where that object that we were returning, it couldn't be retrieved. So I mean, think about like a double delete scenario where two people are trying to look up an item and delete it at exactly the same time. And the second process that arrives goes to get the item to delete it and it's not there but because we explicitly
Starting point is 00:28:28 banned nulls in this particular function we got an error whereas in other languages I mean at worst you return the null you don't think it's going to be null and then you start using it and then you're lucky if the program crashes like much further down the line. I mean,
Starting point is 00:28:45 that's the best case scenario. It could even get worse than that. You just get corruption and things like that. Yeah, so I think a lot of that stuff, and as you said earlier, it is making its way. Like now with C++ 17, there's the optional. Optional is not part of the language so you could do optional foo equals bar and then by default bar is null but yeah there isn't support for there isn't support yet for I wonder if there's a way to, Patrick might
Starting point is 00:29:16 know this, if there's a way in C++ to just blow up, I guess you could have an optional where if you tried to, actually I guess optional have an optional where if you tried to... Actually, I guess optional will do that. If you try to access it, it will kind of blow up.
Starting point is 00:29:30 So in the new C++ one, if you access an optional where the value is missing, it throws an exception by default. But there are ways... You're supposed to check it before you do that or say, give me this value
Starting point is 00:29:42 or this default. Yeah. So this is a common pattern like you'll see the same thing in scala or haskell or swift i assume um and i think that go ahead oh i was just gonna say do you feel actually you finish your thought because i have a kind of tangent so so i think like it so this is a great idea um and it ties in with kind of algebraic data types, which some languages are starting to get, and generally, you know, FP languages have always had. But you can push these type ideas even further, right? Like the phrase that I think comes from like OCaml land is like, make illegal states unrepresentable. Unrepresentable? Yeah,
Starting point is 00:30:27 let's say it that way. Okay. And so to use the type system so that, you know, you can't, like that you could enforce invariance in your code using the type system. And having richer types allows you to do this more easily. Can you give an example? Is it sort of like saying you can't do three plus dog or something like that? Is that, is that where you're going with this? So that's a super, uh, simple one. But so, um, if you have, um, some types, if you have, um, if you have a, a some type, which is like a type that can be one of several values, right?
Starting point is 00:31:08 So in Scala, I would have like, let's say I have like a sealed trait called animals, and then I have a dog cat and parakeet or something, right? And then somewhere else, I have some code that does some pattern matching and pulls those apart and handles each case. And then if I add a new value called goat or something, the compiler will tell me, hey, you have not handled this case. This type has four possible values and you are not handling that case.
Starting point is 00:31:40 Oh, I've seen that. Yeah, you're talking about the case classes classes is that the right word the case classes yeah and so I think this concept of like so that that's like totality checking and some languages take it much further but so when you're when you're writing that actually I think that I'm trying to think of another example uh maybe i'll maybe i'll think of one but yeah using the type system to kind of uh make it more apparent when you are doing something wrong i guess is kind of the concept uh hey jason not to interrupt you but before you go off on that tangent uh do you want to take a minute to tell people about o'reilly os con oh that's right yeah Yeah, OSCon is coming up.
Starting point is 00:32:25 There's going to be a bunch of superstars there that you can listen to. They're going to talk about actually a lot more than open source software is going to be there. There's going to be blockchain. There's going to be AI. There's going to be cloud computing, distributed computing, be a bunch of different talks from people all over the world you can go to oscon.com slash pt for programming throwdown if you go there you can uh you'll get a special deal which uh which is which is really cool um definitely check it out there's going to be a lot of really interesting people do you know who else is signed up to uh speak so i actually would advise people to just go look at the the website because there a ton of people. But I know that there's Holden Crew from Google, Rupa Deshir from CodeChicks,
Starting point is 00:33:10 Julian Simon from AWS, Allison McCauley from Unblocked Future. I mean, the list is really big. Like I was starting to like, I'm going to read. Oh, wait, I'm not going to read all these people. There are a ton of talks. So actually, I've never been to a conference where I know we were talking about this last episode. And, you know, you were talking about it about what it is kind of like to go to a conference. And I feel like going and talking to my boss about trying to be able to attend one, because I think it'd be really cool to be surrounded by people talking about the kinds of things I'm super interested in. Yeah, I mean, also, one really interesting thing that this conference is doing is pretty unique is they have sort of speed networking. They have book signings. They give
Starting point is 00:33:49 you a really good opportunity to meet other people. I've been to conferences in the past where it's just very, very technical. And it was designed for you to go. It's designed for one-way communication, right? For you to go and listen to some talks. But this is really designed for you to interact and meet other professionals, which is really cool. So definitely check it out. You can get 25% off your pass if you use the code PT25. I believe if you use the link, oscon.com slash PTt. You'll also get the discount, but put the code in just in case. And yeah, hope to see you there.
Starting point is 00:34:29 Yeah, so with all of these languages, you know, adopting a lot of these principles from functional programming, where do you see the whole ecosystem going? Like, do you see some of these languages sort of collapsing together? Or do you see there of these languages sort of collapsing together? Or do you see there's maybe going to be, you know, sort of an explosion of new ideas? You know, I always kind of wonder if there be some type of contraction, because a lot
Starting point is 00:34:57 of the features will just, you know, things will just become homogeneous over time. Yeah, I don't know. I don't see it becoming more homogeneous like i only see it becoming more heterogeneous i guess like uh just um like the the number of people developing software continues to grow and like i don't know if this has to do with with functional programming at all but like as you were saying before like if you're writing a service that that other people are calling and some sort of grander architecture, you could write it in whatever language you want as long as you agree on the protocol. So in some ways, we're in the Cambrian explosion of languages.
Starting point is 00:35:38 And I mean, I don't see that going away. Certainly, the table stakes are higher for a new programming language, right? Like you can't just write like a compiler. You know, people expect package managers and they expect like code linters. That's a really good point. Yeah. Is there, I guess Scala has SBT, right?
Starting point is 00:36:00 For the package management? Yes, yeah. Yeah, there's still not a good... Patrick, you can correct me if I'm wrong here, but I don't think there's a good package manager for C++. I know there's Hunter, but it's not even that popular. There are a few, but they don't... I've never found one that had enough critical mass of packages to be useful.
Starting point is 00:36:21 Yep, exactly. There's Conan. There's actually one from microsoft it's i think it's like vc i don't remember but but um yeah you're right none of them um can really get everyone on board i mean it seems like i can understand i mean it sounds incredibly difficult i think like maybe you guys uh disagree or something but like so c++ just existed before the idea that like languages should have should have a package manager um like was an important idea right and i think that there's these stops along the road right like i think go kind of put down its feet on like having
Starting point is 00:36:58 a way to format your code easily and that like languages you know after go are all going to have that like it's such a good idea but but you know languages before that people are too busy fighting and their pr is about whether you should format it this way or that way yeah that's right yep yeah i wonder uh um i really wonder what's going to happen i do think that okay so to your point with Docker, with services, service-oriented architecture, that really gives people flexibility to write any language they want. But I feel like the system is inherently winner-take-all as well. And again, I think there's always going to be a lot of languages i just wonder whether the distribution concentration will just you know favor a few languages like i think you know python you know
Starting point is 00:37:52 we do mostly python at where i work now um you know we use the typing module and all of that um but yeah i mean there's definitely better languages um but i feel like there's this sort of winner take all effect um although although to to sort of playdell's advocate against that um tensorflow recently added support for swift and so that i think is a game changer for a lot of people um you know doing machine learning and people in ai yeah um i had on my podcast uh, Brian Cantrell, and he did this great presentation, and we talked about it about software values, I think it was called. So he was a big proponent of like the Node.js ecosystem and had kind of a falling out with them. And he kind of thought about this a lot and decided that like like what matters with programming languages is sort of
Starting point is 00:38:46 like where they put their values and that it leads to like a different system so like Node.js kind of put a lot of importance on just being accessible like people being able to pick it up and I think when he wanted some more you know thought that there should be some
Starting point is 00:39:02 more complex features that would build more robust software then they were like well that, that would be great, but that would take away from accessibility, right? And I work on Scala, which has a reputation for being very complex. And I think Rust also has and Haskell. So like, I feel like that's the decision space, like as a language, right? Do you want to be like, do you favor this being an easy language for people to take up do you favor that this is language that's that's more reliable or
Starting point is 00:39:29 more secure i mean performance is probably another um aspect but there's all these values right and i think languages kind of pick and choose uh where they fall like c++ obviously has some very specific you know performance and memory usage constraints on it that will be more important than anything else. Yeah, that makes sense. So in the functional programming landscape, is there sort of a Pareto front there? Like, are there reasons to use Haskell versus Scala that involve, I guess, performance? Or is there some speciality that Haskell is particularly good at?
Starting point is 00:40:14 Yeah, so one thing that is interesting about Haskell is that it is lazy. It has a lazy evaluation model. And I don't know any other languages that have that so besides all its its functional aspects it has this lazy aspect which um can can be challenging but has uh benefits in certain cases scala i think is great um when you want to use the jvm um because like you're not going to run into like hey like I literally had this problem with Haskell before where I needed to interact with this like soap web service and they're like yeah don't do that like that was there where if you're in in
Starting point is 00:40:57 Java like if you're on the JVM that's never going to be a problem yeah it's just so much so many billions of lines of code that have been written yeah i don't know if that answers your question though yeah that makes sense yeah i think um yeah the lazy evaluation just to kind of give people more depth on that um because actually it's supported in in um it's it's not it's not part of python by any means but if you're using tensorflow or pytorch or any of these uh g means, but if you're using TensorFlow or PyTorch or any of these GPU tensor processing libraries, they're doing lazy evaluation.
Starting point is 00:41:31 And what that means is, imagine you have a program that it reads a number from the command line, it adds four, it doubles it, and then it returns it, right? So it prints it to the screen, let's say. So when you do the add four and the double, that doesn't really change.
Starting point is 00:41:53 I mean, it changes some memory on your computer, but you don't really notice anything until you do something with that number, like print it. So what a program could do is it could just keep kind of like a ledger of what you said it should do. So you said, oh, you want to, I forgot what I said. I think add four. You want to add four?
Starting point is 00:42:13 Okay, I'll make a note of that. You want to double this number? Okay, I'll make a note of that. And then when you go to print it to the screen, then it goes back through its ledger. And it says, okay, what operations do I need to do? And so, you know, this is a very simple example, but imagine if you did that operation to two numbers and only printed one of them. Well, then it doesn't have to do that operation on the other number, which is just going to get thrown away. It only has to do half of the work. That's a big reason to use ledgers is the pruning but by far the biggest reason is
Starting point is 00:42:45 that there's a lot of latency especially if you're doing anything on the GPU you have to take information that's on your motherboard and you have to send it over to this PCI card and that takes time so you can send a ton of information but it just takes time to get there. And so by batching up all of these commands, you can send, you know, 100 commands instead of one
Starting point is 00:43:14 command. And even though there might be 100 times as many things to do, again, it's a latency issue, not a bandwidth issue. So you get a huge speed up by doing that and haskell has that has that basically baked into the language yeah and like so scala has laziness as well and like a uh call by name is what they call it but it's not the the default so it is a very powerful paradigm as you're saying um having it as the default um, I think that's confusing for people who aren't familiar with it. That is not, you expect a program to work by starting with the first line and then executing through the bottom. Whereas you're describing in a lazy world, it's kind of like, it goes all the way to the bottom, building up its computation and then kind of runs it by
Starting point is 00:44:02 backtracking through what it needs to do. Yep. Yep. And so a lot of these languages or platforms will have sort of a immediate mode where, for example, let's say you're developing and you need to know the value. Maybe you have a variable that you're just stepping through with the debugger, but you're not actually even using it. You still need to know kind of at every line of the code what that value is. Maybe just you have all this computation and at the end you get not a number, right? That's really hard to debug. So with immediate mode, you can kind of step through and say, oh, this is the exact line
Starting point is 00:44:40 where things kind of went south. So it's totally possible. And so in a way, you kind of get the best of both worlds. So it's totally possible. And so in a way, you kind of get the best of both worlds. You get this immediate mode when you need it, which is a little slower. Think of it as sort of features, which we didn't talk about yet, but we get to, that are resolved right away.
Starting point is 00:44:58 And then you also have this lazy mode, which is much faster. Yeah, and I think from like a theoretical cs perspective like the lazy evaluation mode will always be at worst take as much time as the eager mode um because it's you know it can but it can be faster because steps could be deemed unnecessary but um it can have a tremendous memory overhead. Like if you're in Haskell and you want to, you know, maybe they would say just don't do this, but let's say that you're like summing a whole bunch of numbers, but because of the way you did
Starting point is 00:45:36 it, it is following kind of the default lazy style and you're passing around that result number. But the result number, in fact, it's not a memory location of an int. It's actually a giant computation of like add one plus two plus three plus four. So the calculations will end up being the same. But until that's evaluated, you know, they have these kind of space leaks where you end up holding on to a whole bunch of memory without really meaning to yeah that's a that's a really really good point um just in general these higher order languages um will will have sort of traps so i think of it more like uh you can think of it as like using a machete or using uh you know like a chainsaw right like the chainsaw can do a lot more it could could be really quick, but also you kind of have to develop some more skill to use it. And I think that's, it's a good way to sort of learn is to dive in there. You write this program and you realize, oh, why is this taking, you know, an hour to run? And then there's, you know, there's a bunch of really good tooling for all
Starting point is 00:46:44 of these languages to step through and say, oh, i see why it's happening because i'm building this huge computation graph of of uh all of this mathematics i'm applying when really i should at some point um i just realize all of that computation i think they call that checkpointing should checkpoint the computation so that it collapses that whole call graph and then you can start again. Yeah, and what I'm describing is probably like a very much a beginner mistake to not realize that you're chaining around this computation. Yeah, that makes sense.
Starting point is 00:47:18 Yeah. What about... Oh, so by the way, you asked me like, hey, when should you choose which functional programming language? So I'm going to say, you know, always choose Scala because that's my favorite. But I think in practicality, like, you know, a language like Haskell or something is a great place to learn about all these FP concepts. But if you need to do real world stuff, like I said, if you need to talk to some soap thing or something, you know, the JVM is a good place to be.
Starting point is 00:47:48 Yeah, that makes sense. And if you're at a company or you're doing some software task now in a different language, one thing everyone can take away from this podcast is to, you know, realize how to do functional programming in that language. And so just to enumerate a lot of this, I mean, if you're in C++, you can use Folly Future. Actually, Patrick, you might know of other alternatives to that. The only one I've ever used is Folly Future, but there's probably a hundred other ones that basically give you this async await type paradigm.
Starting point is 00:48:24 You know, if you're in Scala or Haskell or something like that, that's very natural. If you're in Java, there's got to be some good libraries, but you're going to be creating a lot of objects. So get ready for a ton of objects. Other language? Oh, yeah. If you're doing anything like Node.js
Starting point is 00:48:46 or even if you're doing React or JavaScript in the browser, definitely look at the await async libraries in Node. I think there's RxJS in the browser. Before we enumerate all of them, look up like it would either either be you know reactive programming functional programming um there's there's a way to do it in every language and depending on the task you're trying to do it could be really powerful so um definitely you know dive into that um and and it's something really good to understand and and types, right? If you're doing React stuff, I don't know, maybe
Starting point is 00:49:25 TypeScript or Flow or, you know, and another keyword I'd call it is like algebraic data types, which more languages are getting support for, but is a nice way to kind of build data structures. Yeah, that's one thing that drives me absolutely crazy about TensorFlow and PyTorch is they just have the tensor data type. So if I have a tensor that's sometimes I've done this where I have a tensor that's I'm going to make sure I get this right. Yeah. Yeah. OK. So I have a tensor. Let's say five by one. So it's a vector. Right. And then I multiply by another tensor that's 5 by 1. So what that's going to do is it's going to multiply those two vectors, and that's going to do a dot product.
Starting point is 00:50:13 So under the hood, it's going to multiply component-wise, add that all up, and I'll get a single number out. So maybe I do this vector times vector, or they're calling it tensor times tensor, or this, you know, they're calling it tensor times tensor, and my output is three, right? But if I get the dimensions wrong, like, let's say one of those two vectors is transposed. So now I have a five by one matrix multiplied by one by five matrix. Well, what sensor flow is going to do is it's going to do the outer product. So my result isn't going to be 3 or 10 or 100. It's going to be a 5 by 5 matrix.
Starting point is 00:50:52 And nothing warns you about that. So you could just easily get blown up because sometimes we have these huge vectors and we multiply them together. Maybe it's a million items. And we expect them to output a number, but what ends up happening is it outputs this million by million matrix. And it can't even fit that matrix. So your graphics card blows up.
Starting point is 00:51:17 Right? That just absolutely drives me crazy. There is something coming out in TensorFlow called Named Tensors. It's not out yet, but drives me crazy they are uh there is something coming out in tensorflow called named tensors it's not out yet but um you know i think to your point i mean it's it's moving in the direction of sort of algebraic types so i mean i think the holy grail there is where you have unit types you can define like you could say seconds s equals 10 microseconds and it would do the conversion automatically stuff like that
Starting point is 00:51:46 yeah uh so like a different holy grail is like if you've actually would encode the size of your matrix into the type so i've seen this i've seen this uh done in a couple languages. So an example in the Idris programming language is actually like he has this function to transpose a matrix. And the way he defines a matrix is it's like matrix and it has two type parameters that is like the n by n size, right? So he has a function that takes in a matrix
Starting point is 00:52:24 that is size n by m. Maybe those are hard to say over audio. I by j, let's say. And then it returns it like j by i, right? So by encoding that kind of dimension into the type, you can actually understand that that is a transpose function, like without even understanding the body of it, right? You can see just by that that these two variables move that it's actually kind of rotating the matrix Yeah, yeah, and if you do You know if you multiply these vectors and you set that equal to a floating num point number then the type system could know Okay, there's only certain multiplication,
Starting point is 00:53:07 matrix multiplication operations that can yield just one number, right? Yeah. And so it would catch that compile time. Yeah. And your example of, yeah, exactly. Returning like instead of a float, some giant matrix. If the type system had that information, yeah, it would be a compile time error. You would never even send it off to run. Yep. Yep. Yeah. I, uh, I'm also a huge fan
Starting point is 00:53:30 of TypeScript. Um, the one thing, uh, it was, it was really hard to set up. Uh, but, but to be fair, I was trying to go for the Holy grail. I did get it eventually. Uh, but what I got was what I wanted was, um, basically the servers and TypeScript running Express. The client was running React, also in TypeScript, and both of them support hot reloading. So what that means is you can edit a source file, hit save, and your server changes underneath. On the client side, every time you hit save, it refreshes the browser and it's up to date. I posted two or three months ago, I posted from Hacker Moon an article on how to do it. It was definitely a lot of work, but it was totally worth it. I think if you're going to build a website, that is the way to go. And as you said, you the type safety which is which is actually really important it's it
Starting point is 00:54:25 saved me multiple times yeah everybody who everybody who whom i've heard talk about move a large js uh code base to typescript has talked about like oh there was a couple bugs that we didn't know about that it just called out and like obviously they're not very prominent bugs because they would have already got to them but But like, you know, if you were developing it in TypeScript, they never would have even been there. Yep. Yep. That's right. And it just helps new people too, who are looking at the code base.
Starting point is 00:54:54 It's very hard to dive into the middle of a code base and know what's going on. But the type system is really sort of your dictionary that you can kind of carry with you as you're kind of diving through all of the code yeah i love that like you know uh maintainability when you have a lot of types like you know we use types quite extensively in our scala code bases probably in ways that would be unusual to people but like when you can go in and say i want to move this here
Starting point is 00:55:23 and you kind of can move it and then see what breaks and then slowly, you know, work those changes through. As opposed to like, you know, some Ruby or Python code base where you better have good code coverage and some great reviews. Like the differences are astounding. So one thing before we jump, I want to jump in and talk about your podcast and other things that you're working on. But real quick, how do you keep people from your team from creating like crazy Scala operators? Because I've seen in our code base some unbelievable operators. I honestly thought they were those Animoji, you know,
Starting point is 00:56:02 those five-letter long uh you know like emojis or they're flipping the table or something yeah how do you keep people from abusing the language well i guess those are two different questions we haven't had the operator uh the operator problem um maybe that has to do with personal uh tastes of on the team. I think that there was a while where that happened. In the community of Scala, that it was common to write custom operators for a lot of things. And I think that maybe that's not the case anymore. But I also think it's a case where if you get used to an operator,
Starting point is 00:56:41 then you love it. You find it easier to understand than than a word or but but if you're not used to it it's very confusing i feel like it's a little bit like like vim like i use vim key bindings and intellij and uh like now that i know the bindings and everything like it's like amazing but you know before i knew it it was like super confusing and i was like why would anyone use this yeah right i went through the same thing uh you know being a machine learning person I know emacs because that's that's what they taught us in in AI class but but yeah I remember the first time the professor forced us all to use emacs what are you doing to us it's like ctrl s to search what's going on but
Starting point is 00:57:20 then over time you realize uh not taking your hands off the keyboard is pretty nice. Yeah. So I think that operators, like it's great that you can do operator overloading. You should only really do it if it's something that's going to be like that. Like you're just going to, you're not going to have to look up what it is. Like if it's going to be muscle memory for your team, like, oh yeah, of course, this means combine two lists together and then increment everything by one. I don't know. Yeah, that's right.
Starting point is 00:57:44 Yeah. and then increment everything by one. I don't know. Yeah, that's right. One thing that trips people up to is the underscore for arguments that don't matter. So just to give people some context, if you have a function and – let me make sure I get this right. A function takes sort of, let's say, say two arguments but the first argument you're not using you can put an underscore just to say hey I know there's supposed to be something here but it's irrelevant instead of putting the word dummy or something like that but then what can happen is you can
Starting point is 00:58:16 end up with like open paren underscore plus underscore close paren and people look at that and think that that's one whole operator right yeah which ties into your other question right like how do you like and people look at that and think that that's one whole operator, right? Yeah, which ties into your other question, right? Like how do you, like Scala is a very flexible language and then so how do you restrict, you know, what people do? Because you can do more than that with underscore
Starting point is 00:58:38 because you can refer to it, right? So you could have a function that is like bracket underscore comma underscore bracket and then like arrow and then underscore dot one and underscore dot two like that's right i mean uh so i think that that is a harder question right like how do you uh i mean i think the same is probably true of c++ to an even greater extent like the language is so large you have to kind of as a team uh reach kind of some sort of consensus but in scala like we use linters and code formatters and kind of enforce things in the build and that that's great like uh something like instead of arguing about code formatting like
Starting point is 00:59:20 nprs we have a config that that kind of dictates what our code formatting will look like. And if you want to argue about it, you could just make a change to that and then argue in that PR where it reformats everything to the new standard, which is just great at removing the diversion of arguing about code formatting. Yeah. I mean, I remember the days of people arguing over spaces and things like that. I mean, it was just unbelievable. And now, I mean, even C++, every language has some type of way to automatically format. And that takes so many of these arguments off the table. It's like, if you don't like the formatting, you could even reformat the whole code base and then just format it back when you go to submit
Starting point is 01:00:01 your PR. I mean, if you're that into it um but but uh yeah i agree with you i think some of the more semantic uh things are just handled in the in the peer review so we have this we have this sort of meme we call clown town and so it comes from the simpsons but i don't watch the simpsons so so someone will have to correct me on that. But yeah, there's basically this emoji we have of Krusty the Clown. And so when something's getting kind of clowny, we put Krusty on it. So if someone has a pound to find that creates a class in C++, they get Krusty, and that's the way we sort of enforce it. We have a bike shed emoji for when people start fighting about dumb things wait what is a bike shed i don't even know um i think it
Starting point is 01:00:54 goes back to this old story that says like you know that they were building a nuclear reactor and they had a committee to like oversee all the plans and then the committee spent all their time arguing about the color of the bike shed because like the idea was that the people on the committee didn't know anything about nuclear reactors, but they understood bike sheds. So they're like, that's what they focused on and argued about. It's kind of like you're missing the,
Starting point is 01:01:17 you're focusing on the wrong thing here. Yeah, yeah. That's amazing. I noticed that, well, you know, it takes a certain personality to invent an entire framework or library or even programming language. And so you have to be sufficiently dissatisfied with the status quo, right? And so when you get a lot of programming language inventors or platform inventors together, you end up with a lot of contrarian opinions. And yeah, I think I need to borrow that bike shed emoji.
Starting point is 01:01:52 Yeah, it's true. You can have too many divas or I don't know what the right word is. Yeah. So tell us about your podcast. So it's co-recursive. Do you, is it purely recursive programming or is it just, is it more general? What's the sort of topic?
Starting point is 01:02:11 So it is not purely about recursion. So the show is an interview format. And so it is a software development podcast. And if I'm curious about a subject, say, similar to this episode, or if I want to know about TensorFlow or some new programming language, I find an expert in that area and bring them on and kind of have them explain that area to me. And I ask questions and I'm hopefully not afraid to say,
Starting point is 01:02:43 like, I don't understand. Could you explain that again? And so that is the format. It's kind of a deep dive onto a technical area, an interview at a time. There's been a lot of shows on areas of functional programming, shows on building your own programming language, shows on Rust, incident response, kind of a wide swath of topics. But I just picked the name because, well, a co-recursive function is something that kind of produces a stream of values. So it's kind of like a pun in that I'm producing a stream of episodes. But really, it's just the name that's distinctive distinctive so what inspired you to get into podcasting um so i was uh listening to a lot of tech podcasts and i i thought that there was
Starting point is 01:03:34 certain topics that i would love to have covered that i didn't really see being covered and originally i reached out to this podcast se daily to see if he would cover some of these topics and he said well why don't you try like just doing guest hosting for the show and uh i did that once or twice and then i just found that it's a lot of fun um like i like to be able to talk to people about software and so uh yeah can't can't stop now oh that's awesome i'll have to make you a trade and i think i can come on your show if you want to talk about any machine learning stuff that would be awesome cool and can people catch you on uh like what sort of social media are you uh you know most
Starting point is 01:04:16 prevalent on yeah so definitely you know check out the podcast at co-recursive.com uh if you you know google adam gordon bell you'll find me i'm on twitter at at adam gordon bell and also at co-recursive and uh yeah cool so if people want to reach out to you they uh do you support uh dms on twitter or should they email you through the website how can people get a hold of you yeah you can You can DM me through Twitter. You can email me, uh, Adam at co-recursive.com and, uh, yeah, check out the podcast. I think it's super interesting. If you liked this episode, uh, and you need more podcasts, I think it's probably a good fit. Cool. Yeah. I mean, we, uh, we get a lot of people saying, Hey, why don't you do more episodes? Um, um, but, uh, but you know, I think that there's, there's a lot of really good producers
Starting point is 01:05:07 out there creating a lot of great content. And, and Patrick and I also have a lot of kids. So one episode a month. And, and, and yeah, if you're interested in knowing more about really a lot of these topics that, you know, that we're all interested in, but especially recursion, functional programming, things like that. Adam does this literally every day. He's very passionate about it. You should check out his podcast and hit him up on Twitter.
Starting point is 01:05:37 All right. So thanks a lot for coming on the show, Adam. I really appreciate it. This is an awesome episode. I think we really dove deep on functional programming if people still have questions don't hesitate to email us you can also ping Adam you can email both of us
Starting point is 01:05:51 but I think we will hopefully we cleared up you know a lot of the mystery around functional programming because it is something that's really difficult to dive into yeah this was a lot of fun thank you so much. The intro music is Axo by BinarPilot. Programming Throwdown is distributed under a Creative Commons Attribution ShareAlike 2.0 license. You're free to share, copy, distribute, transmit the work, to remix, adapt the work,
Starting point is 01:06:27 but you must provide attribution to Patrick and I and sharealike in kind.

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