 a little bit late but we're back up and half power we're limping along um let's see is that one on that other screen yeah but it's just blue yeah you'll just use that as a nice backdrop to our class okay so we talked about the differences so what's the difference between renaming and substitution what replace what free variables yes so that's one of the keys right substitution only changes free variables right whereas the renaming operator just renames everything right what's another important difference between the two substitution okay with substitution you're guaranteed to have the same uh we call the same expression because it just takes away the it takes away a layer of abstraction almost that's what we're that's actually we're going to use the substitution operator for and that's what we went over the last at the end of class on monday that's what the substitution operator uh will be used for right but fundamentally it replaces ids with what that's the other key difference what does it replace ids with expressions right with renaming is just renaming one id to another id right so we can't rename an id to an arbitrary expression that's why we have this substitution operator okay so we went through some trick or we went through some applications of this right so the substitution operator is the brackets and we're having x and we're replacing x with the lambda expression two and remember we're replacing all three x's with the lambda expression two which means that when we see something like this right when we're trying to do the substitution operator to substitute x for the lambda expression two in the lambda expression lambda x dot plus x one is this going to change anything no right because is this x free no this is a bound x right so our substitution operator is not going to change that okay and we saw the other pitfall that can happen right what happens if we're trying to substitute what's going to happen here this is free in the substitution term but it's not going to be free when it's put back in yeah so we want to keep the semantics right of what we're substituting in there right so x is free here but the substitution would cause x to be bound that's changing what we're actually substituting in there right so we change it with something like this well now this x refers to the bound x and not the free x right inside this lambda expression that we're substituting this x is free which means after we do our substitution x should also be free so what can we do are we just we just have to give up in this case what do we do wait do we have to use renaming on the original expression to change the name what so what the x in the original expression into basically anything else yeah so as long as we rename right this x is bound in the original expression so if we just rename this x to whatever we want w y or not y not y right just a new variable that doesn't a new id that doesn't appear in either one now we can do the substitution and now we have something that's semantically the same right this is functionally equivalent the lambda y lambda w dot y w is semantically equivalent to lambda x dot y x so we can actually do this substitution so does that make sense questions on the substitution operator the intuition behind it yeah is it best to change the original expression or the free variable that needs to remain free so if we change this x to a w would this change what this expression does yes so that would be a functionally equivalent change no but yes the w change that x to a w right what does this x refer to a free variable we don't know what it does but it could refer to something else I mean we don't we don't actually know the whole context of this we're just focused here on these days right so if I change this x to a w it's a free variable but now it refers to something else right you think we've been changed the programmer's intention for changing global variables exactly this x refers to some global free x this x specifically refers to this x in the lambda in the meta variable this is a bound x and it's bound to that x in that lambda abstraction so specifically why we don't want to rename the the free x in the substitution okay so what does the substitution operator so formally how are we going to define the substitution operator so we're saying once again right we have e some expression we're going to replace x in that expression with a new lambda expression and right and once again we're talking about free variables right so we want to go through all the cases that a lambda expression could possibly be in and we want to understand what could those values be right so we're basically breaking an expression down into all the different cases so then the case that e is actually x then what's our substitution going to be so if this e was just an x yeah just an n right we're replacing x with n so if the expression is in the form of the exact id that we're looking for then we just simply replace it right so i handle one case what's the other case that's similar to this so what's the case so this is the case that what the expression is what type of a lambda expression an id and what's specifically the condition on that id it is free yes actually we're just looking at one id it's going the id is always going to be free because we're just looking at one expression so it's specifically important about this id in this case yeah that it's x right that it's actually x right so what's the opposite case there where it's not x it's not x right we need to handle the case of what happens if this id is not x let's say it's y right well then we know that operator doesn't do anything right it doesn't change y because it's only changing id's with the same id as x makes sense and we can see that there's no other possibilities that could possibly happen here between id's and id is either going to be equal to x or it will be not equal to x right so you could should convince yourself that that handles all the cases there okay what about function application what we're doing function application so let's say e is a function application so e we want to apply the substitution operator on e and we have e is actually e1 space e2 you just do the substitution operator on e more than e2 yeah exactly yeah substitute right so we distribute the substitution operator to both expressions right expression one and expression two right there's nothing special there about application here now the case comes in now we have to think about what's the third type of an expression we've done id's we've done application abstraction right yeah a lambda expression or abstraction right so what happens let's go through what happens if we have lambda x dot e1 and we're trying to apply x substituted with some expression n what would we do here what's the result here we would first have to rename the x because we aren't allowed to replace the bound variables because it's we don't want to replace the bound variables right so do we want to rename x rename x within the expression so it goes from lambda x to like lambda w um what do you think about that we want to get rid of the lambda x and replace all the x's in the expression with n yes okay we do want to replace all what what types of x's do we want to replace in in this expression right so this is our whole expression e right this is our whole thing e think about this is are there gonna be any free x variables inside e1 because they're all going to be bound to the x yeah any x in e1 no matter where it is is going to be bound either to this lambda x or any other lambda x so it's actually not possible for there to be a free variable with the name x inside e1 so then do we even need to do this operator inside e1 no we just say it's lambda x dot e1 right so we don't actually need to go in there so you can kind of think about it the abstraction kind of protects the substitution operator from going in further into the body but the reason all has to go back to free variables and bound variables right we just kind of prove to ourselves that e1 cannot contain any free x's therefore we doesn't make sense we can't substitute anything in there so we stop okay so then what are the other cases so we have let's say what was our other case before so we had the id here so the important thing here was that the id's were the same right in this case so what's the other case they aren't the same they aren't the same yes look at this you guys are so good at logic all those years of computer science so can I just then say well this is the same thing as lambda y dot e1 applied to the substitution operator but what was the problem that we talked about what problem can happen here when we try to do the substitution what do we have to look out for if n has y in it if n has y in it yeah so we but specifically do we care about if n has a bound y do we care it's a free y yeah so actually we're break we have to break this case down into three different cases so either it's going to be x the meta variable is going to be x or it's going to be not x that's the second case that case is broken down into if let's say free y does not exist in n i'm kind of abusing notation here but i have it more formally defined on the on the actual page right so if the case that y is free sorry is not free in n then we can just do this substitution operator right we can just pass it through and we know this is not going to cause any problems right because we know what we do the substitution it's going to be finding here for this y so what about the case where if there is a free y what if that exists in n then what should we do we replace the lambda y and all y's in e1 yeah so we would need to exactly we're basically going to replace we need to replace this we want to do lambda w dot e1 and we're also going to need to replace all free y's in here with w's and then do the substitution operator x goes to n but let's look at how we okay we've done all these rules we've seen the lambda x case if it's y right so we say that we do the substitution inside of the body of an abstraction if y is not the meta variable is not the same as the substitution variable that we're interested in and y is not a free variable in n so the other idea is okay let's rename it to some new variable y prime where we say it's a fresh variable name so it appears neither in e or n right the new variable name can we always come up with a new variable name out of whatever crazy method you want to use take the longest variable name in e and n and add an a to it that would be one way to do it right and so we're inside e we're going to replace y with y prime and this way this ensures that now all of those variables are going to be changed so that those bound variables so the thing to worry about here what kind of operator are we using in here to substitute y for y prime the renaming operator right but i said the renaming operator is very simple and just it's going to change every instance of y to y prime but if we change a free y from y to y prime is that going to change the semantics of this method of the sorry of the expression e yes so every single instance of y in e is going to be bound at least to this meta variable right and the substitution operator means even if there's other abstractions of lambda y right we're going to change those also to be y prime and we're changing bound variable to n so we're not going to have any problems okay does this make sense questions on this very important component this is the key behind actually doing function applications this is the core crux of the operator okay look through some examples so here if we have lambda x dot x and we want to replace x with foo what's the result going to be what was it lambda x dot x yeah right because the x is the same as the meta variable which means we're not going to go into that expression great okay plus one x replace i'm not going to do this we've done this a hundred times right so the question is how would you actually do this well you would use the i don't remember the number third rule i think you would distribute this operator to each of the plus the one in the two the plus the one in the x and then you would apply each of those operators and you would see that that x would then be replaced with two so now if i have the case of lambda x dot y's x and i'm replacing y with lambda z dot xz now what's going to happen here which of my cases is going to hold change the bound x name change the bound x name in which one here on the left or the right there's a b or n e there's only one yeah there's only one i just want we're being great like so we want to change the bound x to let's say w right and why do we need to change that global x might reference something else yeah the global x in the thing that we're substituting right that x if we just substitute that because there's a free x in what we're substituting we have to change so we say okay the last rule applies we have lambda w dot w x applied first the renaming operator to rename all x's to w's and then the substitution operator is substituting y's for lambda z dot so we'll do the substitution operator it will give us back y w and then we applied or sorry the renaming operator will give us y w and then we apply the substitution operator we distribute it and we finally get lambda w dot lambda z dot xz w okay what if we have something more complicated is it more complicated i don't know so we have this lambda expression x applied to lambda y dot x y substituting x for y z so what's the top level top level expression here free variable abstraction yeah so we have we're going to distribute our substitution operator to the x and then also to the lambda the abstraction exactly so we'll do the first one the left one so this is x so we're replacing x with y z then we look here right and we say oh we're replacing y y is not the same thing as x but there is a free y in what we're substituting right so we have to change every y's here to something else so we can change them to q's it doesn't matter what so we change all y's to q's and then we do the substitution operator we do the distribution again and then we replace the x finally with yz questions on this it's pretty straightforward okay now i kind of made the promise when we started lambda calculus right that you could be able to use this to execute and do computations right to perform some kind of arbitrary computations so what do we mean by execution i mean when you talk about Turing machine what do you mean that a machine kind of executes okay starts executing a process and then what happens so we start executing it then what happens what was that follows instruction yeah follows each instruction until what jump to a different address yeah or it accepts or rejects or halts right at some point it has to like stop computing so you know that the execution is done okay but here we don't have processes we don't have addresses we don't have the concepts of halting we're not even actually talking about a machine all we have is functions so we have to define some kind of notion of execution so the idea is execution is going to be a sequence of terms that's going to be the result of calling or invoking functions so we're going to say that by invoking functions we will get a sequence of execution right so by applying this function we'll get a new lambda expression and then there we can invoke another expression another function which will give us a new lambda expression and we can keep doing that and that will be what we'll consider execution so every step in this sequence is going to be called a beta reduction so we're going to reduce here is a little bit of a misnomer there's no guarantee that the functions are actually going to get smaller right they could actually get bigger but for purposes of this we call a beta reduction so key thing is when can we perform a beta reduction it's basically when we have expressions in the application form so what does the application form mean yeah expression space expression yeah exactly so right when we have something that looks like this well specifically though we need a lambda expression on the left and some arbitrary expression on the right so if you think about this the way we've I've kind of tried to pitch this to you right lambda expressions abstractions are functions the body functions right they take in one parameter their functions and applications are calling that function so this means call this function whatever it is using n as the parameter for that meta variable so you can only do beta reductions if you have something in this form or you have lambda x dot e some kind of expression so it has to be an application form and the left has to be a lambda expression so we're going to find this using the substance this is why we spent a long time talking about the substitution operator because we're defining this based on the substitution operator so based on our intuition right when we had that plus function we wanted to find that function that added one to its argument how are we going to use the substitution operator to do beta reduction here so let's say you have something in this form lambda x dot e space n what does mean perfect yeah so then how does that relate to the substitution operator you would substitute yep yeah this just means right so that we want x to be n so we want every instance of x in the body of e to be n and so we're going to find this very simply as e substituting x for n right so to make sure we take care of all the substitution rules make sure they make free variables and n we properly rename those variables right when we use them this is why doing substitution is so key and so this is one step so applying the substitution operator gives us one execution step and then we get the result of that is some new expression and then we can see can we get there's anything in that is in a beta redux right an expression in this form then we can apply it again and we can do it again we can keep beta reducing beta normal is a form is an expression with node when we can't apply any new beta reductions right there's nothing in the form of application application with the left being a lambda definition okay and the main term the key term we're going to use here full beta reduction is what we're going to focus on there's actually a lot of different ways of how to do execution here and actually it's well yeah we definitely don't have time to talk about it because there's other cool stuff I want to talk about but it actually correlate with pass by value pass by reference pass by name how you do that so you can actually do all of those different parameter passing types with lambda expressions which is kind of ridiculous but we're going to talk about full beta reductions we're just going to keep doing beta reductions until we reach a state where there's nothing in this form yeah you can kind of think of it like that well yes kind of I don't want to make a definitive answer because I don't know 100 for sure so I don't want to say anything misleading it's also difficult because there are no variables I mean there's no I talked about global variables but actually are no global variables so let's look at some examples and then we'll look at we're going to get into how we can actually do boolean logic with this so we can do and or is not all that kind of stuff and then we can actually build up multiple addition and multiplication which is pretty okay so some examples here so we have lambda x dot x y the first question is can we beta reduce this yes we can beta reduce this right we have an application we have lambda on the left and anything on the right so using this operator right so we have x we have our e and we have our n so then what's the resulting substitution operator here and what happens to x yeah x goes to y so we have x and we're substituting x for y that is actually one of our rules so we just simply replace x with y right so this is one step of our beta reduction can we reduce this any further can we reduce y any further yeah there's no application and the left side of the application has to be a lambda okay let's look at something a little more complicated so here I have lambda x dot x y to lambda x dot x and I'm passing I'm calling it with the expression you applied to r so can I beta reduce this thing it's an application that you are no lambda no lambda on the left right the last thing is just you can I there is also an application inside here right we have x applied to lambda x dot x can I reduce that the body of the outer abstraction can I beta reduce this guy yes how would you do that at the body of lambda x so inside here no why not right lambda is not on the left side cool there is only one right there is a the top level we have on the left a lambda we have lambda x here we have a lambda and here we have ur so then what are we going to do place the second x no the second one that appears in the entire expression okay this x with ur so right but we can take it very mechanically right we actually don't have to think that's why we have computers they do stupid things for us right so we can take the body of this lambda expression and we're going to substitute x for ur right when we do beta reduction this is exactly what we mean now this essentially says replace every free x with ur so is it going to touch anything inside this lambda expression no so the result here is going to be ur space lambda x dot x can I reduce this any further right you can't do anything about this look at this now can we have a choice of what to be reduced so can I reduce the zz here no no lamb is on the left can I reduce this guy yes this is an application there's lamb is on the left what about the whole outer thing can I do this probably not going to be easier actually look at it may actually be so it's just going to turn what so let's look right so actually there is the one I think this actually may get more dead call by value call by reference or pass by value pass by reference the order that you do these applications then well we're going to look at the application order doesn't matter we're just going to apply one of the reductions so let's say we do the middle one first or the one inside here right so replace w dot w with z in here so we're going to have zz and we're going to substitute in z for lambda w dot w when we do this now we have lambda w dot w space lambda w dot w so now can I better reduce this guy again yes yeah right I can reduce that it's going to be w replace w with lambda w dot w finally I get lambda w dot w now I can apply this here so what happens when I do this right there is no x inside the body here so I'm replacing y with x I'm substituting inside y x with lambda w dot w which is just y right so everybody see if I had done the outer one first I would have got to y in one step as opposed to six steps I'm going to stick me okay what about something like this lambda x dot xx apply the lambda x dot xx how many choices do I have of what to make a reduce one I don't have one choice so let's do it so inside the body here right are there any free x's in here do I need to worry about that all right so we call the right one what if it has no if it's a lambda expression with no free variables combinator right yeah so there's no free variables so we don't have to worry about any variable rename right so when we do this we're going to substitute x with lambda x dot xx and we're going to get lambda x dot xx applied to land x dot xx can we do can we beta reduce this bring it this it's going to keep going forever so what did we get into an infinite loop you can write infinite loops and turning machines on your coast right you can write an infinite loop in lambda calculus as well right you can never fully beta reduce this it's going to keep going forever okay oh I want to get into all right we need to get into Boolean logic today so that we can have that so that we can cover this other super cool stuff the big thing that you should be wondering about is so we saw we can do kind of loops like this but how do we do recursion when we have functions that have no names right normally a function you have that function call itself because it has a name right you call define a function foo you can recursively call that function by calling foo right but the question is here we have no names we cannot name these these expressions so how do we get recursion out of that so let's look first at Boolean logic does lambda calculus have a true or a false value no that's a program right that's like saying false would be like a program that loops forever but no right we didn't define anything like that so we have to actually define true what is true and what is false using lambda calculus and these are going to be expressions so they're gonna look kind of weird and so did I just what you should think is did I just lie to you by telling you we can't name expressions here so I'm going to find true as lambda x dot lambda y dot x so question is it arbitrary in some sense yes it is arbitrary but you have to once you you have to define what you define as true and what you define as false and depending on how you do that that influences your operators your and your or is your nots right but let's go back to did did I am I lying to you by getting this a name right just for us this is a shorthand for us as humans did I reference t inside of this expression no but with this definition right I'm defining t as this land expression so this means every time you see t you can replace it with this full thing and it's not going to change anything it's going to be exactly the same so we're not introducing variables and variable names into the language we're using this for ourselves so what is this what is this true so what I talk about with currying when we talk about currying if you think about this like a normal function how many parameters does this take in two parameters and what does it return the first parameter yeah you can think of it like a function that takes in two parameters x and y and just returns the first parameter false is going to be the same but the opposite it's going to take in two parameters and it's going to return the second parameter why so using this we can actually write Boolean functions so what property should the function and have how many parameters should it take in two parameters and what should it return either true or false one of the two right we don't depending on the inputs right and it should take in also either true or false right we can't pass in arbitrary values into an and function I mean we can't say and the string atom with the integer 20 that's meaningless right so we're going to find the and function and actually a super clever way and I'm saying this because I clearly did not come up with this so what okay let's go back to basic logic what do we want out of an and function yes only if both the parameters are true should it return true right if either the parameters are false what should it return false so we're actually going to use these properties so keep in mind these properties true always returns its first parameter false always returns its second parameter we're going to find and as a function it takes in two parameters a and b and the body is a b f so then think about that so let's think about the different cases and just think about it we don't have to we're going to dig into the lambda calculus and do all the beta reductions so if a is false what's going to be returned here I don't think so let me check the alright there's a class here at 10 we have to stop alright sorry guys alright