Point free.
ConorShould we? I mean I didn't delete it. We'll actually take before we get to the profiling, let's take a we're gonna take a small interlude here. Welcome to ADSP the podcast, episode 76, recorded on April 19th, 2022. My name is Connor, and today with my co-host Bryce, we continue part two of our four-part interview with Ben Dean on C algorithm. One of the things too that um in in going over uh both the blog that I still have not gone back to find that individual's name, but if you're listening, uh your name will come up in either this episode or part two of this episode once I get to. Uh actually we can just go find it right now.
BryceBecause that's great podcasting serving the internet live.
ConorHere we go. Felipe, I wrote the solutions you guys discussed in this episode. I I'd appreciate if you could have a look at the reduce slash transform reduce solutions. And let me know if this is what you had in mind. Love the episode. So thank you, Felipe. I responded and yeah, it looked good. I only perused it quickly. He was missing one of the function objects or lambdas called max2 underscore accumulating, but other than that, it looked good.
BryceThis podcast is now so big that people write commentary on the podcast.
ConorIt's not that big. Uh I was talking to Jason the other day at the Denver C meetup, and ours is uh not an order of magnitude smaller, but we got a long way to go uh to call it big as being generous.
BryceUm I need swag for C now. Do we have stickers? Do we have a logo?
ConorNo, we put and here's the thing. Uh we one time got a request for uh transcripts. Um, but we have to understand is we will get transcripts as soon as some company offers uh to pay, but it's not cheap to because like I do not have the bandwidth to uh go and you know have them automatically generated and then clean it up. Um and so the alternative is and I I know Ben uh Babryce doesn't have the bandwidth either, and neither does Ben, and neither would he be interested in doing that.
Ben DeaneUm but so you have to get- I did that once. I think it was the Constexpra All the Things talk that Jason and I did, and I think that year um there was a push to get transcripts. Um and you know, Google, YouTube does automatic kind of transcription and just gets it horrendously wrong when it comes to C keywords. Constexpra, you know, that's not a word that Google transcription software has heard of, at least not in 2017. So that was an interesting fix-up.
ConorAnd so that's that's the thing. Bryce and I uh we do really care a ton about accessibility. It's just that it is not it's like they charge by the minute for transcribing that stuff. And uh so if there's some company out here that's listening that's like, hey, I I want to support that and they want to pay for that to get done, boom, we're gonna have transcripts. But I've already got like 16 things on the go, so it's it's not that we don't care, it's that it's that we're cheap. It's prohibitive to do. Don't have the resources. Yeah. Um, and also too, like if I had the bandwidth, I definitely would. I just I currently don't. But back to my question. At this point, we might be on part two of this podcast. Um, is that one of the things that really led me to prefer uh the reduced version or the accumulate version, um, and something we didn't really touch on in the previous uh version is that uh or maybe I'll ask it. I'll ask it in the form of a question. An interview question. I was trying to think of what game show I could do, but I don't have the energy to think of a game show and put it in the right format. Um sort, partial sort, nth element all have something in common that transform reduce and reduce uh and accumulate do not, which makes me prefer those.
BryceWell, sort at least requires random access iterators. Is that true of the others?
ConorUh not what I'm thinking of, even if it is true.
BryceIt is I believe it is true of all of them. That's a bold requirement to place upon.
ConorSo to repeat the repeat the question to the listener partial sort, sort, and nth element all are in one category, reduce, accumulate, and transform reduce are all in another category. What's the difference? That I'm thinking of. There might be multiple.
Ben DeaneYeah, I am correct. Is it the header therein? Algorithm versus numeric.
ConorThat actually, while I was saying it, that popped into my head, and I think you're definitely correct about that. Um also not what I'm thinking of. This is a fundamental property of what the algorithm is.
BryceSomething like the not allowed to Oh, it's uh uh it it it's it's in place. It it modifies.
ConorCorrect. They're permuting algorithms. Right. And that's actually something that I noticed when I was watching the Tyler Weaver video is the first thing he does is create a temporary because he's passing in by cons ref, and he creates a temporary and just copies it for a lot of them. And for an algorithm where you're just pulling out the top two elements, that's kind of irritating that I'm gonna have to permute my input vector or in for input range, if you will, because this is really like a reduction, one of the really nice things I like about uh reductions and transform reduces is that they're very functional in the sense that they're not modifying the input range. Um, and a lot of other algorithms, like anytime you reach for nth elements, and there's not actually an equivalent nth element copy, which a lot of the times you wouldn't actually want this, at least in this case, you wouldn't want that second, as you always point out, Ben, that is it partition copy is one of the only uh algorithms that has two output iterators.
Ben DeaneIt's the only algorithm in the standard that has two. And and actually we should talk more about that in a minute, because I think it's overlooked.
ConorYeah, and so and if you had an nth element copy, which if there's a partition copy, it seems like there should be an nth element copy, but there's a lot of those missing sort of prefix-suffix algorithms. You could use nth element copy to not modify the input sequence, but then you're gonna end up with a range of n minus two elements in you know that one of your iterators pointing to that you don't need. And I think that's actually I can screen share here in a bit if you want to look at um the profiling that uh Tyler did is nth element is actually quite a bit slower than so like I ended up writing my own versions and transform, reduce, and accumulate were definitely the fastest, but um nth element was slower than the uh max element and then erasing a single value um and then doing another max element. And I think that probably has to do with the fact that you're permuting um your your input range. Anyways, thoughts.
BryceWell, what one of the nice things about uh the non-destructive algorithms, um, in particular in the parallel case, is uh you can do multiple different things in parallel on the same data set.
ConorMultiple things in parallel.
Ben DeaneIf you have a read-only data set, yeah.
ConorThat is true, yeah. I guess I don't really think I always think like sort of data flow pipeline-y, but if you don't think that way and you just use it as sort of like an immutable source, then yeah, you can definitely Well I mean put pipelines are just boring graphs, Connor.
BryceJust very boring graphs.
ConorYou just need to think about more interesting graphs than not when you introduce the phi combinator, Bryce.
BryceSomebody has just completed their thesis.
Ben DeaneThere was one more thought that um as I was listening to your last to the to this podcast to your podcast about the algorithms, and Bryce Bryce mentioned, I had the thought, and Bryce mentioned it, that um it's interesting to think about a kind of tricksy way to solve this with min-max element.
ConorIs that possible? You had the same thought.
Ben DeaneIt reminded me, so I haven't worked through it. I don't it is definitely tricky to do because it's it has to be adaptive in the comparator or something. Yeah. Um but it reminded me, does min-max element have an overload? You can pass a comparator to it, yeah.
BryceYeah, of course. Really? Yeah. I mean, what? Yeah, yeah, yeah.
ConorKeep talking, Ben. Keep talking. This is great. I love learning stuff live on ADSP.
Ben DeaneHave you read the paper A Killer Adversary for Quicksort? It's a paper by Doug McElroy. He's he who is the bash Unix. He's often cited as the inventor of bash pipelining.
BryceOh, he is one of my heroes then, because I love bash.
Ben DeaneYeah, he's he's a great guy. Uh um I was lucky enough to attend one of his talks at LambdaConf, I think it was 2015. He talked about Oh wow. He presented 12 lines of Haskell that were a complete a complete framework for manipulating polynomials, including infinite sequences. And I that was just beautiful. Anyway, um highly recommended that that talk. Uh we'll link it in the show notes, so definitely we'll he has this paper, A Killer Adversary for Quicksort, which the the tenet of the paper is um you know we all know that Quicksort performs poorly on certain inputs that can go quadratic, right? If the if the pivot selection is poor. Um and so he constructs a deliberately bad input for quicksort that is constructed adaptively on the fly to bamboozle QuickSort's pivot selection. Okay Um and it's that kind of adaptive nature that I mean that that's what it made me think of that when I thought about this potential min-max element solution to top two. Um because again it would have to be adaptive in the comparator somehow.
ConorYeah, and I I brought up the Min-Max Element page. It definitely not that I doubt you, I just had to confirm. Um because I think I said actually on that episode that Min-Max Element didn't have an overload version that takes a custom comparator, which uh I apologize to both Bryce and the listener. That is entirely incorrect.
BryceAnd uh it will be considered accepting your apology, but I need to. I I appreciate that.
ConorThat's accepted right there. Yeah, well, I mean that's actually that's pretty big uh force. He's from he's a new he's a New Yorker, you know. Uh he's lucky he didn't just write then and there say, you know what, I'm done with this podcast.
BryceI am an aggressive megalomaniac, so that is pretty big of me.
ConorI appreciate Bryce's self-awareness, you know. It's just that uh if he wasn't self-aware, I just uh this guy's a little bit uh, but you know, he's he's he acknowledges it, so it's all good. It is it is important to own one's bullshit. So yeah, maybe um I'm sort of curious if I might I'm I'm I won't be surprised at this point because we've had we've basically had a blog slash uh one blog and one YouTube video, so maybe there's a listener that's gonna go in.
BryceBecause I suspect I will find reasons to object to them.
ConorYeah, let's do it.
BryceAnd this will be this will be uh an instructive uh episode um in uh how to uh produce good benchmarks, or at the very least, benchmarks that pass muster with me.
ConorYeah, so maybe this will I'm not actually sure if this is the start of part three or part two, but definitely this is a great. We're talking about profiling now. Uh let me share my screen. And uh the listener is actually able to go, we'll link this in the show notes and um check out. Oh man. Actually, can you guys are seeing Twitter? Um at the top of whatever part of the Audacity. Oh, what the heck? Stop sharing.
BryceAudacity is the name of the software that we use to record the uh episodes.
ConorWhy does it keep on giving you we're seeing more audacity? Oh yeah. That makes sense.
BryceJust share your full screen. Share you.
ConorI've got two m I've got two monitors, so that would be. That would be I am sharing my full screen, but I just can't share both monitors.
BryceWait, wait, wait, wait. That means we've got to look for anything embarrassing in the tabs.
ConorNo, that's not gonna happen. Although, point free. Should we I mean I didn't delete it. We'll actually take before we get to the profiling, let's take a we're gonna take a small interlude here, Ben.
Ben DeaneI was gonna suggest also put on the stack the algorithm you talked about from the meetup last night. Forget it.
ConorWas the uh oh yeah, yeah, the um yeah, the what's closest to zero and choose the largest of the two. Alright, so we got three things on the stack. What we're gonna talk about for a second here is pointfree.io and a future YouTube video because I got s I got so excited last night and then derailed my meetup for like a good I said I wasn't gonna talk about it for 20 minutes, and then I proceeded to talk about it for 15 minutes and had to like literally cut myself off because I was I was so excited about it. This is what makes the meetup great. I mean, I felt it I was it was a little too I really sort of I it I felt like it derailed a little bit too quickly because I'm not sure how many people were following along, but I was so I was so excited about it.
BrycePeople don't always follow where you're going, but they're excited to to to be on the journey because of how excited you are.
ConorYeah. So all right, on the stack, point free is next. Then we're gonna look at some profiling uh from uh Tyler, and then we're gonna talk about an algorithm we discussed last night.
BryceSo I'm confused about your stack because you seem to have you seem to have inserted at both ends of the stack.
ConorThis is true. All right, Q, whatever. It's a stack because we're gonna pop off in one direction. But that's not what makes it a heap. It's a heap. We had a case. Things have been pushed on by priority and they're gonna be popped off in the other. Exactly. So for context, I have a I have a programming virtual meetup. Um Ben attends from time to time, and I think you've been there for most of the uh seven languages in seven weeks, and we were covering chapter five and programming language four of seven last night, which was Scala. And one of the problems in the chapter was to write a little tic-tac-toe status function that, given a board that is partially filled out, um, determine if there's a winner uh and which the if it's an X or an O, or if there's no winner. And uh, without going into too many details, at one point there's a function that I used in my solution for both a Scala solution and a Haskell solution of a function called all equal to that takes a character and a string. And it basically just determines is the string, uh, are all the characters in that string equal to the character that you specified. So if you're given all equal to the character x and xxx, it'll return true. And if it's xox or x dot x, it'll return false. And in Haskell, I had programmed that by basically all equal to uh with a single parameter e for the character, and then equals and dot map parentheses equal equal e and parentheses. Should we be spelling this out for the listeners? Great radio. But yeah, great radio. And you don't really need to follow it or like be spelling it out in your head, but we went to this site, pointfree.io, because I was like, I could I I said just sort of off the cuff during the um meetup, you could make this point free, but it probably wouldn't um probably wouldn't be as readable because right basically what you're doing is you're mapping a unary function over your string and saying and converting that to a string of Booleans. That's uh true if it's equal to your specified character and false if not. And then once you have that uh list of Booleans, you just do a logical and reduction. And if they're all equal to true, you get a true back. If any one of them is equal to false, you get false back. And so that's basically you could do this with um a transform reduce in C, where you're transforming your characters in your string to Booleans and then doing the logical and reduction. So we plug this into point free.io, and what we get back, it changes the and, which is our logical and reduction, to all, which is the equivalent equivalent of std all of in C. And basically takes a list of Booleans, all takes a list of anything and a unary predicate that's gonna evaluate that uh list of things and turn it into a list of Booleans. And so it turns AND into all, keeps the dot, which is the B combinator, the blue bird, everybody loves the blue bird, and uh and then drops the map and the you and it turns the unary operation into a binary operation. And I'm not even gonna really try to begin to explain what happened there, but basically the B combinator, it it oh, it's I mean, do I do I even attempt, Ben? Do you want to try? It's it's just I'll make a YouTube video and maybe people will understand. But I was so excited. Jean Michel, who's an attendee, he pointed out I was like, oh, I think I understand what's going on. I didn't even notice at first that the and changed to an all. This website is pure magic. Uh Ben, do you have anything to add?
Ben DeaneUh I would just say for the listener, the point of the website is it's called point free because it it changes functions to the point of the function is the argument of the function or the parameter to the function, right? And so it it removes function parameters in favor of plain function composition, hence point free.
BryceSo in in instead, like the C analogy, instead of having a you know, sequence of calls to algorithms where the inputs are explicitly named, having a pipeline of uh range adapters that can be applied to any input where the the uh the input sequence is an implicit in past between all of them. Or you know, the other analogy is like you know, a bash pipeline, um, where you don't explicitly name uh uh you know stood in. It's just implicitly passed from thing to thing.
ConorYeah, Eric Niebler was the first one that pointed because I think at some point I remarked in a meeting or in a conversation he was a part of that I said, oh, C doesn't have support for point-free. And he said, Ah, that's not actually true. If you are building up a custom range adapter, that is the composition of you know a transform and a filter and something else, um, that's technically point-free, because you never mention your arguments, um, which I was like, oh yeah, that's a good point.
BryceUm at the very least, you you never mention your primary argument. In a lot of cases there, you might have an argument of a functor or or some other parameter to one of those functions, but but not the actual input sequence.
ConorYeah, not not the argument that will be required for basically the the callable that is returned. Um yeah, and maybe well, we're probably not gonna have time to get into all these things, but yeah. I've been thinking a lot about higher order function these functions these days.
Ben DeaneWell I was gonna say you made the observation here, Conor. So so the dot operator is is the bluebird combinator, right? Um function composition. Yep. Uh and you you come at this code very much in a combinator mindset where at least you said last night you were you think about combinators, and the way you think about combinators, you know, you can tell me I'm wrong, but um you think of them as functions of one argument. Well, in particular, the the I guess the bluebird combinator combines together two functions of one argument. Right. And looking at this Haskell point-free version uh is not obvious from that mindset, because of course the equality operator is a binary operator, it's not a function of one argument, it's a function of two arguments. Uh and indeed all is a function of two arguments as well. And so uh it it at first glance, you know, in that mindset, it looks like how is how is dot working to combine these two functions because they're not functions of one argument, uh except of course that in Haskell every function is a function of one argument, which can then return a function as opposed to returning the eventual result because of partial application being built into the language.
ConorYep. That's and that's that's like a very even to this day, I have to like when I start thinking about this stuff, I like I have to sit down and start. I think like at some point I'm gonna have to go and implement a mini, it doesn't have to be Haskell, but basically a language that has currying built in because it is it's a very different model, like you said, right? In this code, all dot you know, paren equal equal paren. That's uh the B combinator which composes two unary functions sitting between. So it's an infix operator. It sits between two by two binary functions that so two functions that take two arguments. Right. Somehow, and somehow it works. And somehow it works. It's very even like the uh the blackbird, the b1 combinator, one of my favorite combinators, we talked about it in a previous episode, where that that combines a unary function and a binary function. There's a definition of that where basically three beat combinators in a row, three bluebirds in a row, equals the blackbird. And like I have no idea, like I have not sit down to like work through the eta reduction or whatever you whatever technique you use. But like I've seen that in a talk and a couple other blogs, and like I'm just like, I don't even like BBB, I do not understand how that equals B1, but like that's the whole I mean, Haskell Curry's very first paper on the topic in 1929 was entitled An Analysis of Logical Substitution, and before he had named it combinatory logic, like that's how he approached it. Like programming languages weren't even a thing back then, pre you know, 30s or 40s, and it was it was substituting, you know, one expression for another expression based on these sort of relationships. And uh yeah, I I'm it I you are definitely correct that I come at it from like a very specific, you know, mindset that's primarily of like how they're used in APL, and then I've been sort of Reverse engineering my way into these other sets, you know, or or contexts of Haskell and I came to uh Haskell first before combinators.
Ben DeaneSo I think about this just in terms of how the types unify and check. Pretty much. Interesting.
ConorAnd it's interesting because technically I I I landed at Haskell first, but didn't really appreciate what the dot did or really what the dollar sign did. I just sort of knew that if I stuck them in different places, oh then it'd work. And um and so yeah, even though I saw them first in Haskell, I didn't really appreciate what they were until coming back from from array languages.
Ben DeaneIt's well, it's spring, it's a good time to study combinators. I would say I currently have two combinators living outside my front door. I have there's a I two finches made a nest in my wreath. And for the last month I have been using my front door as a result. They they laid she laid five eggs, of which four hatched, and there are currently at least two baby birds that are still surviving. Oh, but you know, it's it's sad that some die, but that's nature for you. That's why that's why she had that number, I suppose. But yes, they're they're surviving and thriving, as far as I can tell.
ConorAnd the for for the F combinator is definitely uh is a combinator.
BryceThen we're gonna we're gonna need some pictures.
ConorYeah. To add to our show notes. And uh, I do have a picture.
Ben DeaneYeah, uh, we don't disturb them very much, but I do have one picture.
BryceI assumed that you had some some pictures.
ConorYeah, for and for the listener that hasn't heard the lore of Raymond Smullian's uh to mock a mocking bird and why, so a mathematician, famous mathematician that um I think I probably heard about it from you, Ben, um, or maybe if I first heard about uh the book from that uh Point Free or Die Talk that was given by Amar Shah back in like Strange Loop 2016. But then you mentioned um Raymond Smullian and and had told me that he was a very well-known and prolific writer of sort of logic puzzle books and math puzzle books. And he wrote this book in 1985 called Tamaka Mockingbird, where he nicknamed all the combinators. And the reason he gave them bird nicknames is because very famously or not so famously, because I only learned this from reading um Tamaka Mockingbird, is that Haskell Curry, who was, you know, basically did all of the research that led to the field of combinatory logic, he was a huge avid bird watcher, and that's why it was basically an homage to him. And and the funny thing is, is I was at lunch the other day and I'm pretty sure I saw a warbler because I actually, through like investigating combinators and spending so much time researching them and tweeting out photos, I actually am starting to uh recognize types of birds. And I like I fell off my chair and like ran outside the restaurant to try and get a photo of this warbler because I was like, a warbler in the wild. That's the W combinator, it's one of the best ones.
BryceConnor's gonna become a bird watcher. Connor's gonna become like a bird man. He's gonna have like a collection of birds that he cares for.
Ben DeaneThis week, what may be useful, I just heard about this app that's out of um Cornell. Merlin. Merlin? Merlin Bird ID? Yeah.
ConorYeah, yeah, it's like the you just record some audio and then it tells you what it is. But apparently they're doing amazing things identifying birds.
BryceAbout about 10 years ago, my dad, who's a bird watcher, like had that idea like for an app, and he was like, Can this be made? And I'm like, I'm sure it can be, but I'm not the person to make it.
ConorAlright, moving on to, unless do we have anything we want to say about point-free tacit programming before we move on to uh the profiling?
BryceWe should go on to the profiling because Bryce is uh I'm fading fast, it's approaching my bedtime. I don't know how you're still alive given that you exercised more than me today.
ConorUh I'm wired. I'm wired. I mean uh we're talking about birds combinators.
BryceYeah, the crash hasn't happened yet. It's coming. It's coming.
ConorI mean you also have a way earlier bedtime than me, you know. I typically go to sleep at like midnight.
BryceNo, my my bedtime has been disrupted the entire winter. Not entirely because of winter, but because of my bring up the profiling make Bryce nice and angry so he stays awake.
Ben DeaneThere are things wrong here, Bryce.
ConorThanks for listening. We hope you enjoyed and have a great day.