 Wednesday, good news, no class on Friday, but don't throw up, I won't be here. Yeah, so today we are going to start in on Lambda calculus. So next we've got crazy way to think about this, this is the last section of the material that we're going to talk through in this class. Yeah, we're almost done, we're almost done, you're almost out of here. Go on to do other classes and other projects, still have a clue who we could use. Okay, before we start this topic, is this going to be an easy or a hard section? Hard to stop. Hard? Why hard? Why do you think that? Because I had the word calculus in it. Why don't you start using calculus, learning calculus? Like a senior? Anywhere from what, 14 to 17? Did you master calculus? Alright, did you pass calculus? Yes. So it's not that scary as a word, right? You've already done calculus. Lambda calculus has nothing to do with calculus, so that's another thing you keep in mind. So this is me trying to quell your fears, this is not going to be incredibly difficult, this is not going to be calculus level. So what's scary about Lambda? It's free, don't know what it is and it's free. Things that are great are not scary, girls are awesome, as are other great things. So, nothing's going to be scary here, we're going to break it down. I promise you it's going to be a little different. It's going to be different than what we've done in the past, but we're going to learn this together and it's not going to be any more difficult or easier than the previous steps here, it's just going to be a little different. Another bit of disclaimer before we get started, although I guess it's my third time teaching Lambda calculus, so I'm pretty comfortable, but if you look at my background, I'm much more of an actor and programmer background and not a mathematical foundations background. This is why I don't teach 355, because that's not what I'm good at. Here we're going to do things a little bit more formally, so if I make mistakes or whatever, point them out, let's talk about them, it's entirely possible, but I think we have some really cool stuff to cover. So, Lambda calculus breaking it down is just a language to express function application. What's function application? So functions, calling a function in a program. So you know every single word in this sentence, right? It's a language, which means it's going to have blood. And semantics. Yeah, it's a language that's going to have syntax and semantics that we're going to study, and this language is all about calling and applying functions, defining functions and calling functions. And so really at the core of Lambda calculus, this is all it is. And this actually is, so to get you a little preview of where we're going and part of the reason why I'm studying this, you guys have studied Turing machines and computation in that sense, right? So what's a Turing machine? So what? It has a tape, so infinite tape, and what else does it have? It has the current location, and then what can a Turing machine program do? It can read what's at the current head. It can write some new value, or what? Move in either direction. And so why do you study Turing machines? Because before you do? Why do you study them? It's a good model for a machine. Why is it a good model for a machine? It's basic. It's basic, right? It has very simple operations. Infinite tape, read, write, but why? So I could think of a simpler machine, right? It is powerful than CFDs, because CFD has limitations in terms of determining what kind of languages that can be accepted by CFD. Yes, but more importantly, what type of, the types of programs that you can write on a Turing machine? Can you write more powerful programs and see your Java? No, fundamentally no. Anything that you can write in a programming language, you can express on a Turing machine, right? They have the same expressive power. There exists no program that you could express in C or Java that you can't express in a Turing machine. So it gives us this very simple model and says, wow, this is the basic of computation, right? We're computer scientists. We're trying to learn and understand how computers work. This is the base. This is the bottom level of computing, right? All you need is, well, infinite tape and a stupid machine to, like, move back and forth, which to me is super unrealistic. I don't know about you, but I always felt that, like, I feel like they're kind of lying to us. You can't ever build a Turing machine, so what's the point of talking about it? So what that has to do with Lambda Calculus, as we'll see, Lambda Calculus using just function applications. So the only things available in this language are calling functions and defining anonymous functions. Using just this, it has the same expressive power as a Turing machine, and which also means it has the same expressive power as any C or C++ programming language, which is crazy to see that that power of computation can be reduced to just function applications. So this is why actually, even though I don't necessarily enjoy the formalisms around here, I really like and I think studying Lambda Calculus is incredibly important for you, because it is a different model, and it's a different model of computation that's a little bit more intuitive to me as a programmer rather than a Turing machine, which, like, well, how do you build this thing? Like, this is just function calls. So in Lambda Calculus, we can define anonymous functions as we'll see. So we don't have any names for any functions, and we can apply functions. That's it, those two things. And it turns out those are the only two things you need to make a programming language. Sorry, to express computation, I think that's probably the better way to push that. And what's really cool is we think, okay, we'll look and see that this came from, you know, the 30s, which is also kind of crazy to think about, where people came up with this idea, it was 80 plus years ago, and it still influences, and it's not just an idea. So we're going to study the language, we're going to study the syntax and the semantics, but you can see traces of Lambda Calculus in modern-day programming languages. And pretty much the entire family tree of functional programming languages all derived from Lambda Calculus. So languages like ML, Pascal, F-SARP, Closure, there's a lot more. Lisp actually, even though it's not strictly functional, it borrows a lot of ideas from Lambda Calculus. And these ideas and these concepts show up in our, in programming languages that we use every day. So in Python, how do you define an anonymous function? You use a keyword, Lambda, and you say Lambda X colon X times 2 or whatever the body of your anonymous function is. So you are literally using this Lambda, and the reason why they use it is because it comes from Lambda Calculus, in Python. So that can help show why this is important. They obviously thought that those ideas were important enough to include in Python, and to demonstrate that, they used this Lambda keyword. Cool. This is actually fun because a lot of times we don't actually get to go into the history behind some of the things we talk about. I think that will change as CS gets older. But right now, everything we're teaching you, you know, think about how long a computer's been around for. Not that long. So this goes back, this line of thinking goes back all the way to 1893. And there's a bunch of names here. I'm just not going to bunch of them. There's a bunch of those names. Brege, I guess it depends if it's French or German or how that pronunciation goes. Studying to use some functions in logic. So can you somehow use functions when you're defining logical operators, or is it ANDs, NOTs? Could you represent that logic maybe as functions? Further along, Schoenfinkel, is that any... I feel like this is a German name. Is that correct? Schoenfinkel? Cool. And so in the 1920s, he studied how a specific type of functions in lambda calculus, called combinators, which we'll learn about, how these can be applied to formal logic and how we can actually use these as part of formal logic. Church is the person who introduced lambda calculus in the 1930s. He's really where a lot of these ideas come from. But in 1935, two other people, Clean and Roster, wherever you've seen the Clean, the star, right? Same person with this crazy. They showed that actually the system that Church introduced was logically inconsistent. So they showed that there was a problem in that system. And so Church fixed it in 1936 and published what's considered the version of lambda calculus that's relevant to computation. And over the years it's been refined further. There's been other work adding type systems onto lambda calculus as we'll see there's no types. All there is defining functions and calling functions. And that's part of why it's not difficult. As we'll see, the syntax and the semantics are fairly simple. They are restricted just like a Turing machine. You just have function definitions and calling functions, that's it. Questions on history? Cool. Okay, the syntax of lambda calculus. So everything in lambda calculus is going to be an expression. So everything's going to derive from an expression. So an expression could be, I believe, four things. An expression could be just an ID. What's an ID? So an ID is a token that we get to define. We'll use just the ID that we've always been using. So what's the ID that we've always been using as a token? What's the token? What's the regular expression? Yeah, a letter, first has to be a letter and then followed by any number about a numeric. So that's just what it will be. The other type of expression will be lambda ID dot E. And what's the E in this case? Expression, another expression. So that must satisfy these rules as well. So lambda is, you can look up here, we're defining the grammars, or lambda would be a token. I also just realized this is slightly confusing because we're using uppercase letters, both for tokens and for rules. We have E as an uppercase expression, but I think there'll be nothing else besides an E, so that should be fine. The third rule, an expression space expression. That's it. And the fourth rule is parentheses. We can have parentheses. Pretty simple, right? It's simpler than C, the C grammar. Please knock your head a little bit. This is much more simpler than C. Cool. So remember, now we're just talking syntax, right? We have no idea what any of these things mean, and we'll get to that in a second because that is semantics, right? So we need to build up our intuition for what is a correct lambda expression. So let's go through some examples. So an X be a expression, a lambda expression. What about lambda X dot X? So recursively, you say lambda ID dot E. Yes, lambda ID dot. And then an E, an expression, and here you say yes, that's an expression because that's an expression, it goes to ID. What about X space Y? What about lambda X dot Y? Yes? No? Why not? Not a question, I don't know what an ID is. Yeah, but lambda must be followed by an ID and then a dot. An ID is not a lambda, so we cannot have this, right? This is not valid syntax. What about lambda X dot Y, YZ? Yes? What about food lambda bar dot parentheses thing? Probably? You should know. But yes or no answer. Yes? Okay. What about some other stuff? What about that? Sure, what if I put parentheses around this? What if I put parentheses around this? I think you guys got it. If we're trying to parse this, right? We have a grammar, we're trying to parse this. How do we actually parse this last lambda X dot YZ? So if we're going to build a parse tree out of this, we have lambda X dot YZ. How would I draw a parse tree? So what would be the top element of my parse tree? B, they're all expressions. And then what would be the first rule by the branch? Yeah. So we have lambda, we have ID, and then what? Dot. And then what? Expression. We have lambda ID dot E. Cool. So ID is X. And then what would this expression be? YZ. It can't be YZ. It has to be one of these rules. E, E, E, E, E, and then what? ID of X and then an ID of Y. Cool. Is that the only way to parse this? Do you want that on it? How much of your grade are you willing to wait here? Jeopardy style. So how can I prove that this, how can I demonstrate to you and prove to you that this is ambiguous? Different parse tree. Different parse tree that generates the same string. So how would I do that? What does this ego do? It goes to ID, which then goes to X, and this expression goes to ID, and then goes to Y. So who bet that it was not ambiguous and is going to lose points? I don't want to do that. How would it be fun to do it at some point? I've seen, I remember hearing a story about, I think it was like a statistics class where you were learning about like probabilities and also learning about, you know, risks and this kind of stuff. And so what you do is for every question on the exam, you would put next to that question your probability that your answer was correct. And so then they would wait to your grade based on, which is kind of nice, right? So this way it prevents guessing, right? Because you don't just want to choose something. So they had this whole scheme of how to grade this. And anyway, so it's really interesting because they're like tied back into the class. I'm always proud about doing that, but I don't think I will. That'd be too hard to grade. Cool. Okay. So this is ambiguous, right? And the way to think about this is the question is where are the parentheses? Are the parentheses here? Or are the parentheses here? Right? That's the key question. So we know that ambiguous grammars are bad, right? Because we cannot parse them. So how do we fix an ambiguous grammar? We could change the grammar. Or what else? What was that? Is that again? Yeah, we just add. So we can actually change the context for your grammar itself. Or we come up with some convention of what we mean when we write things. And so that's what we're going to do here. So also we can see that this ambiguous is going to come up with x, y, z. Because do we have a graph that looks like this? Or do we have a parse graph that looks like this? Right? So we still have the same problem here. And in the same example we just went through, which we all lost, right? We have two different ways to draw this tree. So we're just going to add, we are going to come up. Well, I'm not going to come up. I'm going to give them to you. We're going to introduce disambiguation rules so that when I write a lambda expression, you know exactly how to parse that. And this works both ways. When you write something on the exam, I know exactly how to parse this. And that way we want to deal with this ambiguity. So whenever we see this, e goes to e, e. It's left associative. So what does that mean? So if I have x, y, z, which happens first? X, y, and the result of that with z. Right? So that's how we will parse these no matter how much there are. They're going to be 10 or 20. They'll always be left associative. Questions? It would be w, x, then y, and then z. So it would be like this. So if you have w, x, y, z, this means with our disambiguation rules, w, x, y, z. So we don't know what this means yet, but we know exactly how to parse it. Not psychic. We're looking at the slides. Okay. The other rule we have to deal with is lambda id dot e. So in our case of dot x, y, which was the correct way to parse it. So the idea is we extend as far to the right as possible starting with the lambda id dot. So for instance, this lambda x dot, we're going to try to parse as much of that as possible. So here this is going to be the same thing as x, y. So we'll try to extend, you think about what we're greedily trying to extend the body as much as possible. So how many parentheses would I have to add? How many sets of parentheses would I have to add here to disambiguate this? Two. Two. Right? So this inner x is going to be in here, and the outer x will be here. Right? Or I guess I should add another one. So the question then is what do I do? So what is the expression that's in? So let's say this is the string. This is my lambda expression. How do I parse this? Well, first it's going to be e, but how do I parse this inside? So I said I'd try to extend this all the way as possible, so I do something like this. Where do I put the right closing parentheses here? After y again. So we extend as far as possible as we can in that body, but obviously we can't cross. And if we think about why this is, right? So this is, we have expression, and then we have expression, and expression, and here we have z, and here we have, let's see, left parentheses, expression, right parentheses, right? And then in here now we have the lambda. So we have lambda, is it id?id.expression. So we're trying to figure out what this expression is, so we extend this as far as we can, but clearly we can't try to repart this expression here, right? These parentheses are forcing this to only be up to here. That make sense? And so then if I added a w here, so this was w, x, y. Yeah, so it'd be here to here, right, to disambiguate this, but then we also have the left association, so we have this and then this. So yeah, this is basically what this is saying. So is this, so yeah, so we have, so here we have parentheses inside the body of the expression, but that doesn't stop us from saying that all of this belongs to the same expression, right? This is the equivalent of this. So this is something that is incredibly important. In order to even do the next things we're going to talk about, I've seen people mess this up and then on the final and midterm you can't do anything because you don't know how to write, you can't read the lambda expression, you can't calculate or do anything with them, right? So these are something you really have to know and work on. So how do I do lambda a dot lambda b dot lambda c dot abc? Yeah, so I have parentheses around here, parentheses around here, and parentheses around here, and parentheses around here, and around the a and the b. Like this. Cool. Okay, any questions at all? This is the time we need to get addressed up. Disambiguation rules about the syntax, about what is a valid lambda expression. No, it will be like this. So we left associated means the left-most thing happens first. Well, okay, not happens first, but it parts. So these are grouped together, then that's grouped together, and then that's grouped together. So we'll get into what this means. When we get into what it means, it'll be a little bit more clear. So this is how w, x, y, z, you get a thing. So we have, let's see, so we can't read something like this, right? Okay, so we'd have to draw, we'd have to have it like this, where this is the body, sorry, this is the expression inside the lambda. And so if we wanted it to be these expressions, if we wanted it to be expression goes to expression, we'd have to kind of do it like this. And I think this second one would be not necessary, but this would mean that we have this expression rule. This would, sorry, parse as e spacing. What's the use? Because we need a symbol, right? We have these rules. We just need some symbol that denotes that we are, have one of these rules. So it means nothing. I mean, I'm just saying it constantly. Yeah, it's just a, I mean, it's a token. You can think of it as just a token of this grammar. It happens to be the symbol lambda. I don't know why. I was actually trying to watch a video beforehand where somebody claims they knew why that church chose lambda as the value here, but it's weird. My sound wasn't working like for my headphones. I still know what's going on there, but apparently it's arbitrary. This could be, it could be lambdas, it could be deltas, it could literally be anything. All that matters is it's consistent with the syntax of the grammar. Any other questions? So now we get into the fun part of what does it all mean? Right? This is, well, not that far up, but what does everything mean in lambda calculus? What do all of these syntactical things actually mean? So we first have to establish some definitions and terminology so that we can talk about things. So every ID that we see in lambda calculus, we're going to call a variable. So that W, X, Y, Z that we saw earlier, W, X, Y, and Z will be variables. Which makes sense. This is a language, I said it when we first started talking about it. It's a language for functions, calling functions and defining functions. So we need some variables. Expression goes to lambdaid.e. We're going to call that rule. So when we see something of this form, it's called an abstraction. You can think of it as a function definition. So this is why when we do anonymous functions in Python, we use lambda because it looks actually incredibly similar to this. We have lambda, X, and then a colon, and then the body of our function. So this is just, and we're going with, this is also kind of what makes this a little bit difficult. We're studying something that was created before we ever had computers and functions and actual things to do this. So they use different terminology. We're going to call this an abstraction. We're going, this is the way lambda calculus is taught. I think it's to keep it close to the original. But the way to think about this is function definition. This is defining a function. The id that's inside there, so in between the lambda and the dot, is called the variable. So this is the parameter you can think of to the function. So we have lambda X dot XYZ. That lambda X, that X means that X is essentially the parameter of that function. We'll see, yes. But we'll also see the super cool thing is that doesn't matter. And so we'll also use the term meta variables. We'll say this is the meta variable X. But we need to have a function. So we have the parameter store function. And this is the thing is, I think about this just like writing your own code, right? You write a function, you have to define what are the parameters, and then you define the body. This is the exact same way in lambda calculus. We're defining the parameter, and then we're defining the body, this E. And so E is called the body of the abstraction. Which is kind of nice, the function body is pretty much the same thing. So this is right. There's only two things that we have to think about that there's only two things that lambda calculus does, defines functions and calls functions. And here, this is defining a function. Now we're going to do the trick when we get to semantics is exactly what happens when you define and when you call functions, right? But for here, at least now we know this lambda ID.E is a function definition. And that's the way we can think about it. So the flip side of that, we can define functions and now we need to call functions. So to call functions is this syntax. Something, space, something else. Expression, space, expression. This is called an application, so a function application. So for the application, the function will be on the left and the thing that we're passing into the function will be on the right. Which actually, and maybe it kind of feels kind of weird because you don't have the parentheses around the function call, but in some languages like Ruby, those parentheses are actually optional. So Ruby function calls look like that. So we're going to have function name, space, and then the parameter to that function. I don't know whether that comes from this. I don't think so. I think it's more like a stylistic choice because Ruby can look very pretty if you look at the code and sometimes if it doesn't have the parentheses, it can look very cool. Okay, questions on this? Super high level. All we have, function definitions and calling functions. That's it. And yet we can still do everything that your C and C++ program can do. You could write an entire operating system in this. I mean, you wouldn't, but you could, right? That's the point. Okay, so I'll start bringing this down a little bit and start digging deeper and deeper into the details. So lambdaid.e is defining a new anonymous function, right? So once again, we have functions without any names. We have functions without any names. That seems crazy. That's one of the things that we'll show that Lambda Calculus can actually do. So I said we can do everything that we can do in C. Well in C we have loops and we have recursive functions. How do you call a recursive function? You use its name to call it again. Here we have functions with no names. And we'll actually see that you can still get recursion even when you have functions with no names, which seems insane. And so also, so the other relation with other programming languages, right, we saw that on Python to define a new anonymous function we use the lambda keyword. In Java, anonymous functions are called lambda expressions and they're directly from Lambda Calculus. This is why. So trying to make links between, it's kind of crazy to think about, right? Things from the 30s that one person thought about are impacting programming languages now in 2000, 2016. I think that's cool. So just as we said, so the ID is the formal parameter of the function, the body is the body of the function. And essentially what we're going to do is when we have an expression, an application, we're going to call function E1, setting its formal parameter to be E2. Where the formal parameter is the meta variable, that lambda x, whatever that ID was. Questions? Yes. Why? Why is, so I think it's in two ways. A, in the context of this class, right? So we just learned all about syntax, semantics, and now we're going to apply those concepts to study this language. We're going to treat it like a language. We're going to study it. But the cool thing is, to me, it's more linking the facts. It's a pretty profound and interesting theoretical concept that this Turing machine, which seems very different than function calls and function applications, right? The Turing machine does not have function calls and function applications. It has the tape. It has move, left, move, right, right, one, right, zero. But that is the same expressive power as this language of function, function definitions and function applications. And it's not faster than function? No, I wouldn't say faster. To me, it doesn't matter because we're not, we're going to think about how to execute it. But it's not necessarily, I wouldn't think about faster or slower really. It's more thinking about the conceptual level. Is it more expressive, right? Or is it less expressive? We wouldn't be studying this if it turned out that this couldn't express programs that were written for a Turing machine or in C, right? But the fact that it can is really interesting, yeah. How do you prove that something is different as a Turing machine and let me talk to this are equally expressive in certain ways? Very carefully. You basically can show, you have to kind of show that any programming construct that you write in one, you can do in the other. And then if you do it the other way, then you can show that they have the same level of expressiveness. I honestly don't, I don't know. You have to look at the papers and how they actually prove it, but I'm sure they have proof techniques. Like the other way, right, is to show that like, I don't know how do you guys do it for like CFGs, that CFGs are less expressive than Turing machines, right? You probably show that there's some pattern that a CFD can't match that a Turing machine can. I can't remember, there's, the church's Turing, I think hypothesis or thesis is that Lambda Calculus and Turing machines have the same expressivity. So they have a whole way of how to prove that. The comments about this beat that even though it doesn't matter. My experience in 240, I think Dr. Rackett is written in C and that parses Scheme, which is similar to this stuff we're talking about, and programs, some of the stuff, the calculations that we ran in Dr. Rackett having coded up its Scheme, the recursion and big number of calculations ran way faster than the C++ would have, even if Rc would have even though the interpreter was written in C, it was able to compute the expressions faster. Yeah, so it's actually a big line of research, especially with functional programming languages. So the big difference with a language like Haskell is that no functions have side effects. So they're just basically mathematical functions. The input, the output is a function of the input. So you can't, it's very tricky then of how you deal with a file system and do all this other state changing behavior, but fundamentally you don't have that. So the cool thing where that gets into performance, now we have all these cores on our CPU. If every function doesn't depend on any global state, that means I can compute each of the functions in parallel automatically. So you, the programmer, get parallelism automatically. And this also comes into play. Anybody use link in C-sharp? Yeah, so you can very easily use p-link, which is parallel link to run link queries and commands and sorting and all this cool stuff in parallel across a number of cores. It was actually super cool. For one of the projects I did for my PhD, we did it in C-sharp and I was able to very easily ratchet up the parallelism because I was able to literally just one-line change of like I think you've added as parallel or something and the link engine knows to run these bits of code across as many cores as you have, so it's really cool. So yeah, so, I don't know. Yeah, there are cases where it can be faster, cases where it's not, I don't know. To me that's not really what we're focusing on here. Okay, let's look at an example. So I like to go through examples. We're gonna do things a little bit backwards. We have not defined an addition function or even one, what one means, right? All we have are variables. We do not have numbers. So let's assume for right now that we do have that. We will actually get to, in a few days, we will get to where we are doing addition and numbers, computation on numbers, without having these things defined. So I'm gonna show you how we will do these things. But for now, just to get an idea of how Lambda calculus works, how these application process works, let's step through some examples, assuming we have addition and one. Everybody good with that? Okay, so let's say we have this lambda x dot plus x1. Why is the plus on the left? Yeah, it's a function. Also, the other thing that's tricky is we only saw functions that take in one parameter, right? A lambda abstraction only has one ID. We will treat pluses if it takes in two parameters and returns one. Well, actually it's about, and so we will step through. I promise this will all be revealed. But to build up our intuition, we need to do some other things. So what would this function be like if you wrote it in C or Python? What would it be? x equals what's x? It's in your function. This is the body of the function, yeah. So what would your function be like? Okay, good point. We haven't talked about this. Okay, yes. So the input is x. And we're adding one to x. The question is what happens afterwards. So just like this, we have the body of the function. The body is plus x1, right? This is the definition of a function. And essentially we're saying increment the argument by one. And so what we can do is when we apply this function. So this function definition by itself doesn't do anything. It's a definition, right? We're not actually calling this function. If we wanted to call this function and pass it, let's say the parameter two, what's going to happen is when the semantics of function application, we're going to replace every instance of this meta variable x with the parameter in the body and we will return that body. Well return is not the right word. We're going to transform this expression by replacing the thing on the right, the parameter with the meta variable and returning that new body. So this is going to replace and when we call this, we're calling this reduction. So we're reducing this function application essentially by calling the function and applying the function. We have to get into that later. I don't know if we'll have enough time to get into that. There are no names, kind of. It's a little, there's only variable names, right? Yes. Anyways, we will deal with that. Maybe. You'll kind of see there are, what's really interesting, is there are different strategies for doing this reduction that gives you pass by value, pass by reference, or pass by name, depending on how you do this. Usually, I don't have enough time to go into that because I want to do, I think what's cooler is looking at ands, ors, nots, additions, multiplication, numbers, and recursion. These are super interesting. So, okay. So ultimately, it's going to reduce to plus 2 1. So the idea is we have lambda x dot plus x 1 and we're applying it to 2. And so we're going to reduce. So when we do our reduction, this is not a smiley face, it's an arrow. Angry face. Plus 2 1, which should return what? Which should be reduced to what? 3. If we had what? So we apply this here. Now if we do this application, using what I said earlier, what's going to be, what will this reduce to? So we take the parameter. We replace the meta variable inside the body with that parameter. And then we return that body. Or we reduce to that body. So here we have plus x 1. So we replace all the y's inside here with 2. There are no y's. So what this reduces to is plus x 1. So we do... Let's see. Which one? Lambda x dot 1? It's getting interesting. No, no, it's okay. I like it. Kind of like this. And calling that with 2. So there's actually, if we look here, Is that true? No. So this happens first, and then that happens. So we reduce this. We replace inside this body all instances of y with 2. And so we have plus lambda x dot x. It doesn't do anything. Just writing ids. It's not going to be replaced by anything. Maybe. We'll see. So we'll see there's a difference. In this... So we can talk about this very briefly here. Here x is what we call a free variable. You can think of it as it refers to something that's outside of this scope. It refers to some x. We don't know what it is. But x here is bound to this abstraction and this x. So we can say that like scoping rules, right? This x maps to this same x here. So when we call this function, this x will be changed. So it's not like a bottom made up example. You apply it outward, inward. Is that how you normally do it, or does it normally do it the other way? Or does it not matter? It does matter. That's also a strategy of how you do your reductions. In all of our examples, it will be the case that it doesn't matter what order you go in. It will reduce to one thing always. But yeah, that's another interesting thing that you can tweak in Lambda Calculus and you get different types of computation. Yes, but you can get into infinite loops sometimes. Depending on what you try to keep reducing something, but if you reduce something else in a different way, that loop would go away. Yeah, I don't fully understand all the nuances. Does this have a sense of accepting or not accepting? No, just reduction. So all we're doing is reducing functions to generate something. So we know when we get to three, we can't reduce three anymore. But we knew here, hey, we have a function application. We can reduce that. Let's apply this function. Now we get plus two, one. Hey, I can do another function reduction. So now I can reduce that to three. And we get to three, we can't do any more reductions. I kind of like to think of it, it's a little weird, but I kind of like to think of it as like potential energy. When you lift something up, it has some potential energy. And so by doing the reduction, you're trying to get closer and closer to the ground so there is no more potential energy. You can't reduce it anymore. And that's what happens when we get to three. The problem is we're talking about computation steps, so you can end up in an infinite loop. That's possible. Okay, so we will stop here and we'll continue on this on Monday. So enjoy your Friday off.