 Alright. Hello everyone, thanks for coming. Today's Monday the 23rd. Any questions on project five that I could answer before we get into some new material? Nobody's gonna raise their hand and so that means nobody's planning on coming off as our objective. Everything is going well. Anybody all the way done? You have to raise your hands. More kidding. You have to raise your hand in front of all your fellow students. Good job. Means it's not impossible. Yay. Anything else? No questions on anything that we've done and covered? Yeah. Yes. This is the last main topic I'm gonna go over before the end of the semester. Assuming, you know, maybe, I don't know, maybe it turns out that we get this done in two weeks, but it's helpful. But we'll see. It's a fun topic. Any other questions? Class stuff? Cool. Alright. Well now we get to get into our new final topic, which is land a calculus. So some of you have asked me a little bit before, kind of, I think somebody made the comment that it sounds scary. So why does it sound scary? Calculus. Don't you all have to take calculus? You passed it, right? You passed, you're here, so you must have passed calculus at some point, right? Huh? Doesn't mean you understood it. That doesn't go well for people who are passing this class. Like if you pass, pass and understand. Actually understand is my goal. Passing is my problem. So I guess, I don't know, maybe if I called it like fizzbop, would that make it better? Doesn't have the word calculus in it? I think so. Okay. Well, there's no, I mean, it's calculus because it is math based and very formal. But that's pretty much where the similarities lie. You're not gonna be integrating anything between no derivatives. You don't have to worry about that at all. The lambda part doesn't scare you. But there's like a lot of Greek letters. How do you guys think it's Greek? Is it good? Yeah, it's good. Okay. So at its core, so actually before I get into the lambda calculus, I want to talk about something else. So I really hope, okay, so what do you remember about Turing machines? Any program can be represented by a Turing machine. Any program can be represented by a Turing machine? That's one thing. What are Turing machines? Turing machines are, they have a control unit. They have an infinite tape. It's one side of an infinite tape. And they have some kind of configuration. Just one. Just one thing. They can have multiple, oh, just one thing from here. Okay. So in this, so we have a Turing machine, right? The infinite series of tape, some control head. What else? Yeah. There could be an input language and tape language that are input language. Yeah, some kind of input language or tape language. So we want some way to move the head by the, which one would you call it, the machine language? The tape language. Yeah, yeah. What else do we need? Yeah. Kind of a sub-state. A kind of what? A sub-state. A sub-state. What's that? A sub-state. Ah, a sub-state. Yeah, some way to know if the Turing machine finishes computation. Yeah, that's a good one. We have the ability to write to the tape, right? We can write either ones or zeros or whatever kind of symbols you want. Has any of you ever, maybe for like a science fair project in another school, built a Turing machine? None of you? And you all try to be computer scientists? Just kidding. So why can't you build a Turing machine? What was that? Theoretical. A lot of things are theoretical, right? You can still build them. You can't have internet memory. Yeah, so you can't have internet memory, right? So that's one of the defining features of a Turing machine is that it has an infinite amount of memory, right? So that tape. So when we say memory, right? A Turing machine doesn't actually have memory, it just has this conceptual tape that extends infinitely in, I think, either direction or you can just do one direction maybe. So, okay, it's very impossible to build that, right? So why do we care? Why do we talk about Turing machines so that I can quiz you on it? Do you want to speak a little louder? Is there a decent mathematical representation in the actual view? Bring me my decent. Right. So one of the nice things is, hey, we define this pretty simple. A Turing machine is complicated, but just like calculus, you've all got through that and passed it and understood it, right? So you understand Turing machines, right? You can understand how they work. And so you can maybe prove properties on Turing machines and because all of our computation for algorithms that we write in whatever programming language can be actually implemented on a Turing machine, we know that whatever holds for the Turing machine holds for those programming languages, right? So it's a nice kind of simple conceptual way to think about computation. Is it actually simple though? Is it easy to program if you've ever written a program for a Turing machine? It's really weird and long, right? You have to have the states and you have to remember, again, in the state and I read this symbol, which way do I move the head? I don't know what state does that put me into the language. Right? It's kind of a headache. And so, okay, so Turing machines, so they're complicated, right? They are the most simplified form. Does it resemble anything like the C++ Java Python programming that you do? Somebody's saying yes. No, almost nothing, right? It almost has nothing to do in common, right? You don't have this infinite. You're not thinking about tapes. You're not thinking about symbols. You're not thinking about ones and zeroes. You're thinking about variables and operations on those variables. Maybe if you're doing an object oriented language, you're thinking about objects. You're thinking about methods on those objects. Okay. So the reason why I bring this up and the reason why I think Landik Agnes is really crazy interesting and why I'm super excited to teach it is that it turns out, and we'll, I think, see this more towards the end because we need to build up a lot of formalism to get there, but it turns out that Landik Agnes and Turing machines are equivalent. So any function that you can write in Landik Agnes, you can express with a Turing machine, and any Turing machine can be represented as Landik Agnes, and I think my mic just went out. Okay. How's, oh, maybe, oh, maybe this will work. Hello, hello, full volume. Okay, this is going to be weird, but I guess we'll try. Is it better than this? Same. Okay. Let's just go with this. It makes, preserve my voice from my off-time singing. Okay, I don't need to do it. I mean, not my individual. Okay. So back to what I was saying. So it turns out that Landik Agnes can express anything that Turing machines can express, and so, and what we'll see is Landik Agnes is a language to express function application. So whereas Turing machines deal with tape and deal with a program written for that that can read symbols and move this head left or right and write symbols. With Landik Agnes, all we need to care or think about is just functions. Are you all familiar with functions? Please say yes. Yes, right? You write programs that hopefully have some kind of functions in them, right? Otherwise you're just writing one long program, and that is definitely not maintainable. So to me, this is the thing that is incredibly interesting here. As we'll see this language, keep it in the back of your mind that, wow, every program that I write can be expressed in Landik Agnes, which seems crazy because it's so simple and it's just function application. So that's why I really like it. So there's basically two things you can do in Landik Agnes. You can define anonymous functions. So what does anonymous here mean? Not name. Yeah, what is that similar to that we've talked about before? What was it? Landis. Landis? Close. Are we actually talking about that? We mentioned it. What about other things that we studied that were maybe on the midterm and the last one, say? Don't bring that up, huh? Types. Types, yeah, anonymous types. Well, what are anonymous types? Types without names. Yeah, types without names, exactly. So anonymous functions without names. And then we have the ability to apply these functions. So another way to think about that would be invoking the function if we were talking about, like, a programming language. But these are the only two abilities you have in Landik Agnes. A lot simpler than normal calculus, right? Yeah, only two things. You don't have to learn anything else besides these two things. So who's done some programming in functional programming languages? What kind of languages? What was it? List. List? Yeah, list has functional programming elements. Pascal. What was it? Haskell. Haskell? Yeah, Haskell, or I don't know exactly how to pronounce it, but yeah, definitely super functional programming languages. Scheme. What was that? Scheme. Scheme? Yeah. Scheme and other in the list family. What was it? Swift has function a lot. Really? I didn't know that. That's the new, I say new language that Apple made for the Objective C replacement. Cool. Yeah, I'd like to hear more about that. Functional. Functional calls in C sharp. In what way? Right. So as you'll see, so functional programming actually has a fairly precise term. Basically means no. So actually it turns out that functional programming drives pretty straightforwardly from lambda calculus. So functions are first class citizens. You can pass functions to a function. You can have an array of functions. You can have an array of array of functions, all that kind of stuff. And what you'll find is that when you start playing with these languages, they map very simply back to lambda calculus. This is one of the reasons also that I really like it. Unlike a Turing machine, which you have to be convinced that, OK, yes, any C program that I write could be expressed in a Turing machine. With lambda calculus, it's very simple. You can see, OK, here's how functions are defined. Here's the process for applying a function. And then I can see how computation is performed. You can have real programming languages that do that. Yeah. JavaScript is not considered. JavaScript is not considered to be functional. Yeah, so that's the thing. JavaScript has functional elements, even common list and scheme. They have functional aspects, but you can also write. So what's the opposite of functional programming? Procedural. Procedural or imperative programming. Yeah. So something where you have a series of statements that you want executed. Whereas functional programming is you have functions that you want to apply, basically. So yeah, languages mix both in there. So something like ML or OCaml, you can kind of do both. Haskell is very much. It's got to be everything's got to be a function. So yeah, so a lot of languages, ML, Haskell, F sharp, closure, which is a list derivative that runs on a JDM. It's kind of fun. It has some cool things. So all of these really owe their existence to lambda calculus. So that's another cool reason. Any questions before we go forward? OK. Now a little bit of history lesson. Oh, I guess I should clarify before we start. We are going to treat these kind of like we did with regular expressions and syntaxes. We're going to treat this very formally. It's not really my background. I'm much more of a hacker systems person rather than like a theoretical mathematician. So I'm relying on the 400 eyeballs. Well, the theoretical 400 eyeballs that exist in the audience to point out any inconsistencies or problems. So together we can do it. OK. So a little bit of history. So this isn't something, lambda calculus isn't something that I came up with. Actually, the really interesting thing is that the first kind of uses of what eventually became lambda calculus started back in like 1893, which is pretty crazy. So why is that interesting? I mean, not that date specifically, but before computers, literally BC, right? So before they didn't have any computers to program on. They didn't have mainframes. They didn't have computers. We're not even going to thought in anybody's mind at this point, right? So back in 1893, and these are all German names that I'm going to mess up, Frigging. Very good. He studied the use of functions in logic. So you all looked at like logic a little bit, right? Like first order function or first order logic, that kind of stuff, right? So he was trying to look at how do functions fit in with these logics? What can we do with functions? That kind of stuff. Then later on in the 20s, right? So getting kind of up to modern era. Hey, do you speak German? Can you pronounce this name? I shouldn't think of it. Shouldn't think of it. Okay. So he studied in the 1920s, he studied a specific type of lambda calculus called combinators, which are a specific type of function that we're going to get to, and how those could be applied to formal logics. And actually there's a whole branch of logic called combinatorial logic, which is derived from his work that is all about combinators and how to use them in logic. Okay, then we get to the real introduction. So in the 30s, right, which is also before computers functionally, right? Church introduced lambda calculus in the early 1930s. So he wrote papers on the topic and was talking and presented pretty much what we are going to see in these lectures as to how what lambda calculus looks like and what it is. Then it turns out two other people found out that well, actually the system that you presented is inconsistent. So it actually allows you to derive, it allows you to state paradoxical statements. And they showed this in 1935, and then church was like, well, good, I'm going to fix that. So he fixed that, in 1936 he published basically the chunk of lambda calculus that's relevant to computation, which is what we're interested in. And then they refined it further by adding type systems and doing all kinds of cool stuff to lambda calculus. So if people were doing this in the 30s, it should be very easy for you guys to do it now, right? It's like 80 years on those guys. 80 is almost 90. Questions? Okay, cool. So how do we define a language? Satisfying some criteria. Okay, yeah, set of strings that satisfies some criteria. Yeah, what else? So there's too many things we need when talking about like a language that we've been talking about for like programming languages, yeah. Syntax of the language. Yeah, exactly. So we need to find the syntax of the language and we need to find the semantics of the language. So the syntax defines exactly what each of the strings in our language, what's a valid string in our language, exactly. And what do semantics define? Yeah. How they should be used together? Yeah, how they should be used. So what is the meaning behind those strings, right? What do they mean? How do we evaluate them? What do they mean? So the nice thing is everything in lambda calculus is an expression. So that's it. So expressions have four different forms. See, it's already super easy. Four different forms. Okay. We have that an expression can go to an ID. So I'm using ID here just to be consistent with what we've been using as identifiers, but it could be pretty much any symbol you want. You can define a set of symbols. There's no limit on what symbols can and cannot be used. But for here right now we're going to use IDs and a lot of the examples will use single variable IDs or single letter variable, single letter IDs because that's simpler. Everybody get that? Expression is an ID. Good. All right. Then we have expression goes to lambda ID dot E. So what's the E on that side? Expression. Expression. Yay. Oh, looking good. So good at grammars. Okay. The next one, expression goes to expression space expression. Then we have expression goes to left parentheses expression, right parentheses expression. So that's it. That's it. Four things. These are the only four things. Questions? Comments? Concerns? Yeah. The dot is like the multiplication. What's the what? The dot is not like concatenation. Like we looked at regular expressions as actually the dot. I guess I should have specified, but it'll be going very clear in the examples. So yeah, the only types of, there's only four tokens in here. There's only the lambda character, an ID, a dot, and left parentheses, right parentheses. Yeah. So that's a white space instead of... Yeah. It's, well, the white space here is important between the two expressions. So white space is fairly significant, but a lot of times it's pretty clear from the usage how it should be parsed. But I will try to do everything I can to make sure it's actually in this order. Like lambda, space, ID, space, dot, space, expression. The parentheses, I won't really be too strict about that, right? That doesn't make sense. So they're pretty easy to parse human-wise. The space between expressions is very, very important. So what do these things mean? Exactly. No idea. It doesn't matter yet, right? All we're talking about right now is the syntax because we want to understand what do lambda expressions look like. So with this, could you generate every possible... Can you generate valid lambda expressions or lambda calculus expressions? Yes. You've even written a program that could take in this as input and calculate first and follow sets here, right? It's pretty cool. Okay. Okay, so let's look at some examples. So we're going to go over some examples and we're going to say are they expressions, lambda calculus expressions, or are they not? All right. I feel like a game show host with a mic up here. You're not going to win anything except for knowledge, which is the best. Okay. X is X a lambda expression. Yes. Expression is ID. That's the very first. There's only four rules. One of them is parentheses and the other one is just an ID. Right? So X is a valid lambda expression. Yes. Awesome. Lambda X dot X. Is that a valid lambda expression? Yes. Which rule does it fit? How's it parsed? Second rule? Yes. Second rule and the ID goes to X and the E goes to ID goes to X. Yep. X, space Y. Yes. Which one is it? Third rule. Third rule. Expression, space expression. What about this? Lambda, lambda X dot Y. No. Why not? What was it? Two lambas can't be next to each other. Two lambas can't be next to each other? What was it? Okay. It fits? Yeah. Why? I don't know if you're able to be which one is it? I don't know. But if you're able to do that, what would it mean? Lambda be an ID. Can lambda be an ID? What's an ID? What have you been using for an ID this entire class? Yeah. In our definition, right, it's a character followed by any number of characters and numbers. You said it could be any symbol last one. It could be any of the symbols except the ones that are already defined. Okay. Good point. All right. So this is definitely not a lambda expression, right? Because lambda expression is lambda followed by an identifier followed by a period followed by an expression. So here this doesn't match because we have lambda, yeah. What is lambda? Just a symbol. I mean, it's a Greek letter. Yeah. It doesn't. It has no semantic meaning. It just, I mean, it does now because programming languages have adopted this terminology for defining anonymous functions. But no, there's no reason why church used lambdas versus some other character. I mean, they're probably like a weird historical reason that would be hilarious. I don't know, maybe this cat accidentally hit the, I don't know if it's a typewriter, but I don't think there's three letters there or something. See, I guess the short answer is I don't know. But it doesn't have any, it doesn't mean anything, right? It's just a symbol. It looks cool. I like that. Lambda x dot yz. Yes? So how do you parse this? Two and then three and then one. What about this? Very mixed on this. Yes. Going to describe why? Yeah, in the back. So the first, the food is from the ID. The third rule first. Right? And then the first character is the first rule. And then the lambda and then the other ID dot parentheses expression and other parentheses expression and expression expression. Perfect. Yeah. So this is definitely a valid expression, right? So here we just have an expression on the left followed by a space followed by another expression. And that other expression is a lambda followed by an ID followed by a dot followed by an expression where that expression is parentheses, expression space expression and that expression is expression space expression. See? Simple rules, simple rules. Okay. So let's go back to this one. I'm sorry. No, let's go back to this one. The second to the last one. So lambda x dot yz. So, how do we parse this one? I forget. The third rule, second rule first. Wait, so, okay. So this left one is, so this one is the lambda, this one is the other expression. Is that the only way to parse it? You do it the other way, too. Second rule and third rule. Right. So you do it the other way, right? You could parse this first, the second rule and then the third rule. So what does that mean? Grammar is ambiguous. Yes. So look at this. It's also a good final review. Okay. Yeah. So we have a problem, right? We've defined a grammar that has ambiguous syntax. So what do we do? Keep it and just do what? Just say, that's fine. It's from the 20s and 30s. Like, it's fine. Yeah. In the grammar? Yeah. So one way would be to rewrite the grammar to enforce some strict ordering, right? So to make the grammar unambiguous by rewriting the grammar. That's something we could totally do. What's another thing we could do? Yeah. Add another little bit out. What is it? In the parsing, you could add a little bit out. Yeah. So we can change how we parse it, basically, by adding, essentially what's called the disambiguation rules to the parsing to say, like, hey, this is how we, you know, in case this situation comes up, here's what we need. Okay. But let's look at why it's ambiguous. So what about this, this expression? Is this ambiguous? Yeah. Yeah. Why? What's one way to parse it? Yeah. You could go, Yeah. So you could have, well, so you could have, let's see, you have the left expression out like this, right? So you have, so these are the parse trees. I remember these from way back then. So we have an expression and then the right one is the Z and here, I've gotten rid of expression goes to IV just because it makes this a little bit more clear. Then we have expression goes to expression with IVs. What's the other tree here? The other way. Right. So with X as the left most, top most child and then expression and then Y and Z, right? Okay. All right. So this is one case where we definitely have ambiguous syntax. So this was rule three, right? Expression goes to expression, face expression. Okay. Then the other thing we looked at was this one, right? Land to X dot XY. So what were the two different ways to parse this? So the second rule, so parse it as a lambda expression where this, the dot XY is within the expression and then it's expression, face expression, right? So I think, yes, okay. So lambda X and then an expression and then an expression of X and an expression of Y, right? So this is one way to parse it. What's the other way? You do two expressions and then that happens. Right. So then if you basically switch these around this is the top most node. We would have expression is two expressions. The right most expression is just Y and then the left most expression is lambda X or lambda X with an expression of X. Yeah. So for these trees you're not going to do the dot? For these trees, no, I just left that out because it's kind of, I could also have left out maybe the lambda but I think it's a little bit more clear with that in there. But yeah, there's like a, the tree gets a little big at some point. So is this a big problem? So yeah, kind of the answer is it depends, right? So if, I mean we haven't even defined what these things mean, right? So it could be fine, right? So this is addition. It doesn't really matter what order you do addition in, right? You could have, let's say if these, sorry, I'm going to go back to this other thing, right? If these expressions were instead the addition operator then it doesn't matter what order these things happen, right? Does it matter if you add, if you're adding three numbers, if you add the two numbers on the left before the two numbers on the right? No. Doesn't matter. But, we do need to fix this. So, yeah, these have, things have two different semantics meanings of which we're not going to get into until we talk about semantics because I want to make sure that we've got the syntax down because it, I mean these things look really weird, right? You don't normally see things like this. Unless maybe you study language back to the slide. Okay, so we've got to add some rules. So the first rule we're going to add and this is outside the grammar, right? So this would be any parser that's doing this grammar has to support this. So, the, what was the first rule that we had to fix? Which is? E. Right. E goes to E space E, right? So what we're going to say is this is left associative. So what that means is when we see something of X, Y and Z the way that we mean that is that the parentheses group things to the left. So it means which of these parentheses are going to be grouped together first? X, Y. X, Y, exactly. So this is what this means is that X, Y, Z is going to be X, Y then Z. So does this force is this string ambiguous? No, right? With the parentheses we know that that means that is an expression, right? The parentheses are part of the grammar. Right? So we're saying, hey, treat an X, Y and Z as this. What about this? W, X, Y, Z. Which ones are grouped? Let's say grouped first. You tell me. It sounds like a question. Right, exactly. So we have W, X grouped first. Right? And then that's grouped with Y and then that's grouped with Z. Right? So it doesn't matter as far out as we go anytime we have some kind of potential potentially ambiguous ordering of these expressions where we have expression X, space, expression. Then we know, okay, this is exactly what I mean. I mean spaces. Perfect. Okay. What was the second rule that we needed to fix? Yeah, expression goes to lambda ID dot expression, right? So what we're going to say is that, okay, this is going to extend to the far right to the, as far right as possible starting with lambda ID dot. So you can think of that dot extending, think of it like greedily if you think about regular expressions if that makes sense to you. It's extending as far as it possibly can. So lambda X dot XY the example we saw. So what would that be parsed as? Yeah, exactly. So lambda X dot parentheses XY. Right? So we're saying that that expression that's inside that lambda X dot that expression that expression tries to extend as far as possible. What about this? lambda X dot lambda X dot X. So is this valid syntactically? Did I throw something in here to trick you off? Did I? Oh, no. It is valid syntactically. I hope. Okay. Tell me over here. Tell me how this would be parsed. You have to raise your hand. Yeah. lambda X starting from the right side lambda X dot X the axis and the parentheses but then that's in the parentheses you had that second. So where? So have you ever parenthes- parenthetized? I don't know if that's a word. How would you do that? So that for this right is in its own parentheses. Which one here? X dot X. Yeah. X for this right axis. This right axis? Yeah. It's in its own parentheses. Okay. After that first dot that entire thing is in parentheses. Yeah. Very good. So yeah, that wasn't something that I actually didn't include these parentheses in here and there's a mistake in there. S. Okay. Last time we tried that. So look at this. Proud sourcing slides. Perfect. Yeah. So the idea is that this first lambda X dot this whole thing is an expression, right? So those things would be as if they were in parentheses. And then this middle one, this X is, you can consider in parentheses but that's pretty straightforward. So I need any questions on how we're parsing these. So if I give you some stuff on the exam you'll know exactly how it should be parsed and interpreted, right? Yes. Awesome. Okay. So let's look at some examples. Okay. What about this? Is this lambda, parentheses, lambda X dot Y and parentheses X is the same as lambda X dot Y X. Do you think no Y? Because if you used the rules you just gave, you would do Y X first instead of the X dot Y first. Yeah. So, yeah. Yes. So on that side on the A dot parentheses part it was like together the Y X but on the other side since it's already grouped together in those parentheses that makes it same as the other side. Yep. Exactly. So the parentheses mean that I'm explicitly grouping these together. So when I said the dot extends as far as it can, right? It can't extend past this right parentheses because this is going to get parsed. Those parentheses are going to get parsed together, right? So it's something to keep in mind. Okay. What about this? Oh, yeah. So this is the same thing as this, right? So that doesn't make any sense. It is the same thing. Good. It is the same thing. It's a function. Sorry. It's rule two, right? Sorry, no. Rule three. It's an expression, space expression for the left expression is a lambda ID dot expression. Alright. So how would we parenthesize this? X dot left, race, left parentheses, X, right parentheses, space Y. Left parentheses, left parentheses, right parentheses, space Y, right parentheses. Yep. Just like this, right? So we're going to extend that there. What about this? This is more complicated one. So if you had questions like this on a title, you'd be able to do them. This is fun, because you're going to get closer for emphasis. Okay. What would this be parenthesized? Disambiguated as before the lambda B here? Yeah. Okay. Alright. Here? Yeah. There'd be one before A. Before A? Here? After C. Two more after C. Are you missing one? Yeah. It's going to vary from the corner there. Before A, you have two. Yeah. So yeah, exactly, right? So you're extending every of the third rule the expression, right? You're extending all the way as far as you can. So that's each of these lambda A, lambda B, lambda C. But then also you have this expression A, B, C, A space B, space C, right? And we said that that is parsed left-associative so that the parentheses are here on that. You're only missing one parentheses. That's a tricky question. It depends. If the answer is only one parentheses, then yeah, you'll probably miss that question. If you forget it on something where there's like 20 parentheses, it'd probably be proportional. I don't know. It all depends on the question. Any of you who know this, know that it kind of looks like this, you end up getting the crazy parentheses. It just can be fun. Okay. Any questions? Syntax? I already got the syntax down. Got the disambiguation rules. Locked and loaded, ready to go. Cool. Okay. So now we're going to talk about semantics, right? What these things actually mean, right? So first we're going to find some terms that we're going to be using throughout this whole thing. So every ID that we see, so we've been calling them IDs, right? Because they're identifiers, but really what we're going to do is call them variables. So we have functions and we have variables. Crazy different than anything you've known before. I know I'm blowing all of your minds. Whoa, variables. Okay. All right. So then the two, what are the two main forms that we have from our syntax? So from our syntax rules, right? So some of them are trivial, like parentheses. Some of them are also trivial, like expression goes to ID. So it'll be the two ones that are actually interesting. Expression, those two, expression, expression, space expression, so, yeah. Lambda ID.expraction. Okay. Let's go with the lambda one first, since this is called lambda calculus, so clearly that must mean something. Okay. So what we're going to say is that the lambda ID.expraction is called an abstraction. Right? So that's what we're going to call it. It's an abstraction. The ID here is called the variable of the abstraction, or we're also going to call it the variable of the abstraction. And we'll see why in a bit, but this will make sense. And E, we're going to call the expression E here, we're going to call it the body of the abstraction. Right? So you got to kind of remember this what goes back to the history, right? So the people creating these things, we're doing this way before programming languages. If we're doing this nowadays, we'll probably call them other things, which we'll get to in a second, but for historical reasons we're going to use the same names because that it makes it more difficult to talk to other people, because that's what I know everyone's going to do after this class. Okay. Any questions on this? So we have the meta-variable and the body, the body of the abstraction. This is pretty easy. Okay. All right. Now we have the second syntax, which is expression, space expression. Right? So, it's, well, okay, I don't want to do that, it's not a great practice. So this is called what we're calling a function. So, essentially, I think we can get to it in a second, but, like, so this form is basically defining a function and this is calling a function. Okay. So this is the way to think about it. So we're going to go over some informal semantics today because I want to get you thinking about how, what the semantics are like here, kind of where we're going. So how are we going to want to, how is lambda calculus and how can it even look like or resemble a programming language? Okay. So you can think of it as lambdaid.e defines a new anonymous function. Right? So this is a function with no name. The body of the function is e so the expression e describes the body of the function and the meta variable, the id, is the parameter, as we'll see. So I think people have said they've seen the word lambda before in connection with programming languages. So what languages and where have you seen that? Yeah. In scheme, when you, was it when you define, when you define functions, you use the key word lambda? Probably. I don't think I've done much, if any, scheme, a bit more list. But interesting. Yeah. In the newest, yeah. So in Java, I believe 8 is when that was introduced. Java 8, it's actually how that appeared. So this is why, so this is really why in, they're called lambda expressions in Java 8 and you actually use the key word lambda. So what other languages do we have to? Yeah. And what? C and C sharp. C and C sharp? Okay. I was going to say. Find out. How do we unlikely but possible? Yeah. What else? Yeah. With the newest, C plus plus 11 and C sharp. Yeah. Definitely. Here. Yeah. Python. Yeah. Python. You can use the lambda key word to define an anonymous function. Anything else? Ruby I believe. Ruby, I think, actually. But there's multiple ways there's blocks. There's always multiple ways to do it in Ruby. Yeah. I think that's right. I think you can define I don't know if you use lambda explicitly but probably something like that. Yeah. I think I'm not sure if this keyboard is going to live in. Right. They're called. Yeah. They're definitely going to be called lambda. Lambda expressions or some kind of lambda function. Yeah. So I guess they're right. Huh? Okay. I don't know. I don't know. Maybe call all comes back from lambda guy for this. That's why that name lambda appears in all these programming languages nowadays. Okay. So you can think about it when you're looking at these. Right. So we're going to define the precise semantics but the informally the way you should be looking at it is okay. This defines a new function. E is the body of the function and the ID is the formal parameter of the function. That's it. Huh? Is that the name? The ID would be not the name of the function. But it's the name of the formal parameter to the function. And the body is like the body of the function. Right. So that's pretty easy. So if you have like lambda x.x there you have a function an anonymous function that has one formal parameter x. And then a little bit more informally. So okay. So when you're applying a function or function application you can think of it as calling that function. One is a function that you're calling and you're setting its formal parameter to be E2. So E2 is that second function. So that's what expression space expression means. Alright. Let's look at an example. Okay. So first so did I define any like built in you think built in quote quote functions here? No. I did not. Because there are none and we'll see that you can actually build it. But let's assume for the moment since we haven't got into that let's assume that we have the function plus define and we have the constant one define. Right. So somehow those are already defined. So now we can do this. We can define a function. So what is this translate this to me in normal programming mode. Yeah. So we have function application. So the way if we go back and look at how function application works. Well the thing on the left is the function and the thing on the right is the parameter that we're passing to that function. So here you can think of it as a function x and I'm passing in x we get to in a second we get there in a second. So yeah. So this represents a function that adds one to its argument. So this is all that this does. Right. So pretty simple. Okay. Now how would we actually apply this function? Like let's say we want to apply this to I don't know the constant two. So that's how we would want it to go but how do we represent that. So right here we just first remember what is the return? This function here if I put this in and I like a like a lambda calculus evaluator and I put in this expression what would return value of x plus 1 what about a function? Right. This is a function. You're not applying that function to anything so it's just a function right. It's like if you've typed in if you've defined a function into your I don't know re-pole or whatever good job. So how do I actually use this function to make it do something useful? Yeah. Wouldn't it just be X space the parameter you're passing? X space the parameter that we're passing. Why X? So does this define a function named X? No. What does it define any? Yeah. You can impose the entire lattice of pressure and then add the two closest to the parentheses and write. Yeah. Yeah. So that's very good. Let's go back. So this right here, this is defining a function with no name. This function does not have a name. The name is not X. That's an important thing. X is the parameter to that function. So the thing about formal parameters, you're defining a parameter that takes in certain formal parameters. This function has one parameter. And what's the name of that parameter? X. X. Boom. Yeah. So if you use X outside, it doesn't make sense. X only makes sense inside this function where it refers to that formal parameter. So if we took this function definition, put parentheses around it, right? And then after that, did a space two. Yeah. Why doesn't the first one have my? Does the first one need parentheses? So does the first one, does this need parentheses on the X and the Y? So if I gave you this and told you that this was disambiguated, would you be able to do that? Yeah, how would you do it? Put parentheses around the plus and the X and then put parentheses around before the plus after the one. Yeah. Exactly. Yeah. So that's why you write it like this because I know that you should be able to disambiguate it. So we haven't gotten into what that exactly means. So if your answer is no. So if I give you this or if you write this, we both know how to disambiguate it so we'll know we get to the same thing. If you were to write this and you meant something else, then you're going to have problems because that doesn't mean that. So disambiguate it on that. Yes. The plus and X and the Y problems. Yes. Yes. And you think so. We change the language instead of being ID, we add kind of a plus symbol in there too. Expression would go to an ID. ID in this case is plus. Plus is just another function that we can have defined somewhere else. So this would be, yeah, exactly. I can't remember where we said it but, yeah, this would be disambiguated by, we got parentheses around the plus and the X and then parentheses from the plus to the one. And that would be the function definition or the function there. So then here, right, so here you can think about this as calling this function. Right, so what did I say kind of informally the semantics are for function application? Right, so it's basically replace the formal parameter with the right, with the right expression. So in the left expression, replace the formal parameter there with the right expression. So you can think this is equivalent in programming terms. We want to call this function by supplying two for X and we would reduce this function by replacing X with two. So we would get plus two, one, and which would, we'll see how, but it'll actually, what we call reduce down to three. So see, we had this big complicated expression and this is where I get to think the term reduce comes from because we're reducing it and making it simpler by applying these application rules until we finally get the result three. So we've done some actually, well, maybe not super interesting, but we've actually done some computation just within anonymous function So how do you define, well, get to it a little bit, but how do you define this plus operator? Can you define what you normally think of as a plus operator? What is, let's say, the function signature of a plus operator? Left-hand side, right-hand side? Think of it like a function, not like an operator. So what's the difference? This isn't like a really difficult question. What's the difference between an operator and a function? Yeah, one takes in parameters. So if you were writing the addition operator as a function, how would you write it? What would its signature be? Like the definition? Anybody? Take in how many parameters? What type? Numbers and returns what? A number, yeah. So it takes in two values, returns one value. So can you write that function as a function? What? So I kind of said that the the function application, right, we're replacing the formal parameter. So could you write a function that takes in two arguments? And what we've defined so far? Yeah? Ah, parentheses. Wait, parentheses. So what's a function in this language? An expression, a lambda expression. Yeah, that has a lambda in it, right? So think of this like a function. You're defining a function here. So think about this function that we defined here. How many parameters does this function take in? One. One. How do we make it, can we change this to be lambda x comma y dot something? Would that be a valid lambda expression? No. No, right? So does this completely kill our language because we can, so how many parameters can our functions take in? One. Only one. Right? So does this completely kill the applicability and usability of our language that we're defining here? Can you do nesting? Maybe. Does it work all the time? So the question kind of is, right, how can we write, so even getting into specifics, how can we write a function like plus that takes in two formal parameters to return a result? Right? Or does it have to be two? How do we write a function that takes in three or four or five or six parameters if we have a language where we can only take in one parameter? Take in one at a time? Yeah? I mean, could we just replace one with a function? Replace one what with a function? Like in this case, replace one. So in this example here, let's say we have the plus two one. Right? What we really want is a function that takes in two parameters and returns their addition, right? But we know from our disambiguation rules that this is actually going to be applied as plus two and then that result as whatever that is applied to one. Right? So if we were to draw parentheses around this, we have parentheses around the plus and around the two. So that happens first. And then whatever that reduces to, we're going to apply one to that. Do we really kill everything? Should we go home? Don't answer that. What was that? Yeah? Exactly. We have a language that only has functions that take in one parameter. Yeah? They could return another function. So say that again? You could call it a new plus two. If that was like a return function, then you could apply that function to one. Yeah. So we could actually think, okay well what if our plus function instead of returning an integer, our plus function takes in one number and then returns a function that takes in one number and adds that to the original number. And then when that gets returned by plus two, so plus two you can think of as returns a function that adds two to whatever the target is. And then that gets applied to one so then one gets replaced there and now we actually do one plus two. So this is definitely you guys have rediscovered mathematics from the late 1800s, early 1900s. Which is good. It's a good sign. So this is called currying. It turns out it's like a misnomer based off of curry, who was the one who kind of popularized it. Basically it's a technique, a proof and idea that says hey you can actually if you have a function that takes in multiple arguments you can automatically translate that to a series of functions that each take in one argument. So this is exactly what it is. So it's technically currying is a way to do that. It's also a proof that if your language supports functions that take in one argument then you can support functions that take in n arguments. Yes. We don't have to worry about three have special proof cases for functions that take in five parameters or some function that takes in one parameter. So we kind of actually went over this. So basically what we're doing is we want to define so we would kind of define our addition, it's a little bit wonky here. We're going to find it using addition we're going to define a function that takes in two integers and adds them together. Essentially somebody I think was on the right track we were talking about nesting earlier. So we have here a lambda expression we're defining a function whose body is the definition of another function that takes in parameter y and then it adds plus x and then plus y. So is this a valid lambda expression? Would you know how to parse this? Do a parse string? Yes? Yes? Okay, so we can take this function we can apply it to a value like one. Right? So if you think about this right, so what did I say? How does function application work here? So what do you mean by apply? That's kind of the question. So how do we actually do that application? Yeah, so we replace the variable before the dot with whatever is on the right hand side, right? So we're going to place everywhere we see an x we're going to replace that with the constant one. Is that fine? Yeah, we can do that. So what does that return? A function. Yeah, exactly. It returns a function or it reduces in lambda calculus terms. It reduces to a function that takes in one parameter which, what's the name of that parameter? Y. What does it do to Y? Adds one to that. Exactly. Yeah, so this is curving. So we can define our function here basically takes in two parameters. Right? Even though each function in the nesting only takes in one parameter. So let's look at it actually. So this is applying it to one parameter. Let's apply it to two parameters. So how would we disambiguate this? How is this disambiguated? Which one am I going to apply first? 10. Yeah, so I'm going to apply the 10 first to this. So when I do this application I'm going to replace x everywhere in its body with 10. Right? I can do that. I'm just going to reduce this. This is the application process. It's also called reducing. I'm going to take this 10 change x everywhere to be 10. And so I do. So I have lambda y dot plus 10 y. Yeah, that's right. Okay. And then apply it to 20. So now can I do this application process again? Yeah, nothing stopping me from doing that. Right? So then I replace y with what? 20. And then so I have plus 10 the results of that plus 20, which is going to be 30. Right? So basically this is I'm not going to do it formally, but this is a demonstration that hey as long as you can return functions, right? In lambda calculus and even in other programming languages you can easily write as long as your language supports functions that take in argument at least if your language supports functions that have parameters of size one you can support functions of any size parameter. Simply with doing this. Can you go the other way? Can you go the other way? Could you take a function of one and turn it into a function of that takes in an n number of arguments? Yeah, you just apply those functions, right? You just do it like this. So if you had somehow you wanted to support that or something like this it's just the opposite here. It works full place. So you can go full directions. Okay, let's cover something really quick. Okay, free variables. So, now you're getting to the semantics we need to, we're going to define precisely what we mean by application. So to do this we need to define some terms so we know that we're talking all about the same thing. So, there's two ways to think about this. So a free variable is a variable that does not appear within the body of, basically, okay. So a free variable is a variable that's not in the body of an abstraction that has a meta variable of the same name. It sounds really confusing. But it's actually very simple. So the opposite we'll get to in a little bit but a variable that's not free is bound to the name of the meta variable. So it's enclosed within a function definition. For instance, is x free in this lambda x dot x y z? No, why not? Exactly. So x is the meta variable in this function. You can think of it like a programming language, right? x is the formal parameter of this anonymous function so it's not free. It's always going to refer to this x here. Right? Whereas y and z, where are they specified? Nowhere. Exactly. Yeah, they're not specified yet. Is y free in this expression? Yeah, right? Because it's not bound to any meta variable. It doesn't have the same name as a meta variable in the body of the abstraction. What about this? It's a tricky one. Is x free? It doesn't matter. Yes, it is free y. Right, so inside this expression here, lambda expression, x is not free. Right? Because x is the same name as this meta variable. But here, this x is not does not have an enclosing abstraction. There's no meta variable with that name. What about this? z in this. x, y, z, z, y, x. No, not free, right? It's bound, this z refers to this z here. What about this one? Tricky one. Is x free? Yes, this x here is free, right? Even though there's not an x in there. Okay, great. See you every Wednesday.